☰ Reliability / Error handling
Docs / Reliability
Error handling
Every failure throws ZpiError or a subclass. The base class carries status, code?, raw, and requestId? (from the x-request-id header) — include the request id when reporting issues.
| Class | Trigger | Status | Extra fields |
|---|---|---|---|
| ZpiInvalidParamsError | Parameter validation failed | 400 / 422 | errors[{ path?, message? }] |
| ZpiExecError | Scraper ran but failed | 400 | error, errors, context?, project? |
| ZpiBulkCapError | Bulk item cap exceeded | 400 | cap?, submitted? |
| ZpiAuthError | Bad or missing API key | 401 | — |
| ZpiPlanGateError | Plan tier too low | 403 | requiredPlan?, upgradeUrl? |
| ZpiBulkNotEnabledError | Bulk disabled for endpoint | 403 | — |
| ZpiNotFoundError | Scraper/endpoint not found | 404 | — |
| ZpiMethodNotAllowedError | Wrong HTTP method | 405 | — |
| ZpiIdempotencyError | Idempotency key conflict | 422 | — |
| ZpiRateLimitError | Rate limit exceeded | 429 | limit?, used?, window?, retryAfterSec?, retryAfter?, requested? |
| ZpiServerError | Backend error | 500 | — |
| ZpiDisabledError | Endpoint disabled | 503 | — |
| ZpiNetworkError / ZpiTimeoutError / ZpiAbortError | Transport failure / timeout / abort | 0 | cause |
| ZpiMcpError | MCP JSON-RPC error | 0 | code, data |
ZpiInvalidParamsError
Trigger: Parameter validation failed
Status: 400 / 422
Extra fields: errors[{ path?, message? }]
ZpiExecError
Trigger: Scraper ran but failed
Status: 400
Extra fields: error, errors, context?, project?
ZpiBulkCapError
Trigger: Bulk item cap exceeded
Status: 400
Extra fields: cap?, submitted?
ZpiAuthError
Trigger: Bad or missing API key
Status: 401
Extra fields: —
ZpiPlanGateError
Trigger: Plan tier too low
Status: 403
Extra fields: requiredPlan?, upgradeUrl?
ZpiBulkNotEnabledError
Trigger: Bulk disabled for endpoint
Status: 403
Extra fields: —
ZpiNotFoundError
Trigger: Scraper/endpoint not found
Status: 404
Extra fields: —
ZpiMethodNotAllowedError
Trigger: Wrong HTTP method
Status: 405
Extra fields: —
ZpiIdempotencyError
Trigger: Idempotency key conflict
Status: 422
Extra fields: —
ZpiRateLimitError
Trigger: Rate limit exceeded
Status: 429
Extra fields: limit?, used?, window?, retryAfterSec?, retryAfter?, requested?
ZpiServerError
Trigger: Backend error
Status: 500
Extra fields: —
ZpiDisabledError
Trigger: Endpoint disabled
Status: 503
Extra fields: —
ZpiNetworkError / ZpiTimeoutError / ZpiAbortError
Trigger: Transport failure / timeout / abort
Status: 0
Extra fields: cause
ZpiMcpError
Trigger: MCP JSON-RPC error
Status: 0
Extra fields: code, data
import { ZpiError, ZpiPlanGateError, ZpiRateLimitError,} from "zpi-sdk"; try { const data = await client.run("social:instagram", "profile", { username: "instagram", });} catch (e) { if (e instanceof ZpiPlanGateError) { console.log("upgrade:", e.requiredPlan, e.upgradeUrl); } else if (e instanceof ZpiRateLimitError) { console.log("retry after", e.retryAfterSec, "s"); } else if (e instanceof ZpiError) { console.log(e.status, e.code, e.raw); }}import { ZpiError, ZpiPlanGateError, ZpiRateLimitError,} from "zpi-sdk"; try { const data = await client.run("social:instagram", "profile", { username: "instagram", });} catch (e) { if (e instanceof ZpiPlanGateError) { console.log("upgrade:", e.requiredPlan, e.upgradeUrl); } else if (e instanceof ZpiRateLimitError) { console.log("retry after", e.retryAfterSec, "s"); } else if (e instanceof ZpiError) { console.log(e.status, e.code, e.raw); }}Docs menu