Errors
Three typed error classes. track() captures per-destination failures into DestinationResult.error and never aborts the fan-out. Use instanceof and .code / .platform when you catch.
Hierarchy
ts
import {
AdscapiError,
PlatformDispatchError,
PlatformHttpError,
} from 'adscapi';
// Base
class AdscapiError extends Error {
readonly code: string;
readonly platform?: string;
// name = 'AdscapiError'
}
// A single platform's dispatch failed. Captured per-destination by track() —
// never aborts the fan-out to the other platforms.
class PlatformDispatchError extends AdscapiError {
readonly cause: unknown;
// code = 'platform_dispatch_failed'
// message = `[${platform}] ${String(cause)}`
// name = 'PlatformDispatchError'
}
// Non-2xx HTTP response from a platform endpoint. Carries status so retry
// logic can decide retryable (5xx/429) vs terminal (4xx).
class PlatformHttpError extends AdscapiError {
readonly status: number;
readonly body?: string;
// code = 'platform_http_error'
// message = `[${platform}] HTTP ${status}`
// name = 'PlatformHttpError'
}Fields
| Class | code | Extra fields |
|---|---|---|
AdscapiError | string (caller-supplied) | platform?: string |
PlatformDispatchError | platform_dispatch_failed | platform: string, cause: unknown |
PlatformHttpError | platform_http_error | platform: string, status: number, body?: string |
How track() uses them
Inside conversions.track(), each destination is wrapped:
ts
try {
await withRetry(() => p.dispatch(event, secrets));
result = { platform: p.key, ok: true };
} catch (error) {
const wrapped =
error instanceof PlatformDispatchError
? error
: new PlatformDispatchError(p.key, error);
result = { platform: p.key, ok: false, error: wrapped.message };
}
// → Promise settles with DestinationResult[]; the other platforms keep running.Example
ts
import {
createAdscapi,
AdscapiError,
PlatformDispatchError,
PlatformHttpError,
uploadOffline,
sendWebhook,
} from 'adscapi';
const ads = createAdscapi();
// 1. track() — per-destination errors are strings on the result, not throws
const results = await ads.conversions.track(event);
for (const r of results) {
if (!r.ok) {
// r.error is wrapped.message from PlatformDispatchError
console.error(r.platform, r.error);
}
}
// 2. When you catch a thrown AdscapiError (offline, webhooks, direct dispatchers)
try {
await uploadOffline({ platform: 'meta', csv });
} catch (err) {
if (err instanceof PlatformHttpError) {
console.error(err.platform, err.status, err.body);
// retry.ts treats 5xx / 429 as retryable, 4xx as terminal
} else if (err instanceof PlatformDispatchError) {
console.error(err.platform, err.cause);
} else if (err instanceof AdscapiError) {
console.error(err.code, err.message);
} else {
throw err;
}
}
// 3. sendWebhook throws a plain Error on non-2xx (not AdscapiError)
try {
await sendWebhook({ url, secret, payload });
} catch (err) {
// Error: Webhook delivery failed: HTTP 502
}
// 4. Narrow on .code when instanceof crosses bundle boundaries
function handle(err: unknown) {
if (err instanceof AdscapiError) {
switch (err.code) {
case 'platform_dispatch_failed':
case 'platform_http_error':
return { retry: err instanceof PlatformHttpError && err.status >= 500 };
default:
return { retry: false };
}
}
}Related
- conversions.track() —
DestinationResult.error - Offline conversions
- Webhooks