Error Handling
Every configuration, transport, and validation failure throws AISecSDKException with a typed
errorType property. (The only exceptions are programmer errors in the low-level pagination
helpers: paginate() throws a plain Error on a repeated cursor and collectAll() throws a
RangeError for a negative max.) Transport failures also carry facts that callers can use without
parsing the message:
| Property | Meaning |
|---|---|
failureKind | 'http' when AIRS returned a response; 'network' when fetch rejected |
statusCode | Actual HTTP response status; absent for network failures |
retryAfterMs | Valid server retry guidance normalized to milliseconds |
Configuration and response-validation errors leave these transport fields undefined. The metadata does not contain credentials, request payloads, URLs, authorization headers, or raw response bodies.
Error Types
| ErrorType | Value | When |
|---|---|---|
SERVER_SIDE_ERROR | AISEC_SERVER_SIDE_ERROR | 5xx responses from the API |
CLIENT_SIDE_ERROR | AISEC_CLIENT_SIDE_ERROR | 4xx responses / network failures |
USER_REQUEST_PAYLOAD_ERROR | AISEC_USER_REQUEST_PAYLOAD_ERROR | Invalid input (bad UUID, oversized content, invalid AI Gateway write body) |
MISSING_VARIABLE | AISEC_MISSING_VARIABLE | Missing required config (API key, client ID) |
AISEC_SDK_ERROR | AISEC_SDK_ERROR | Internal SDK errors |
OAUTH_ERROR | AISEC_OAUTH_ERROR | OAuth2 token fetch failures |
RESPONSE_VALIDATION | AISEC_RESPONSE_VALIDATION | 2xx response body failed Zod validation or JSON parsing |
Usage
import { AISecSDKException, ErrorType } from '@cdot65/prisma-airs-sdk';
try {
await scanner.asyncScan(batch, { numRetries: 0 });
} catch (err) {
if (err instanceof AISecSDKException) {
if (err.failureKind === 'http' && err.statusCode === 429) {
console.error(`Rate limited; server delay is ${err.retryAfterMs ?? 'unspecified'}ms`);
return;
}
if (err.failureKind === 'network') {
console.error('Network failure; an async POST may have reached AIRS:', err.message);
return;
}
switch (err.errorType) {
case ErrorType.SERVER_SIDE_ERROR:
console.error('Server error — retry later:', err.message);
break;
case ErrorType.CLIENT_SIDE_ERROR:
console.error('Bad request:', err.message);
break;
case ErrorType.USER_REQUEST_PAYLOAD_ERROR:
console.error('Invalid input:', err.message);
break;
case ErrorType.MISSING_VARIABLE:
console.error('Missing config:', err.message);
break;
case ErrorType.OAUTH_ERROR:
console.error('Auth failed:', err.message);
break;
case ErrorType.RESPONSE_VALIDATION:
console.error('API response shape changed:', err.message);
break;
}
}
}
Retry Behavior
The SDK automatically retries on transient errors:
- Status codes: 500, 502, 503, 504
- Network failures: Retried within the same retry budget
- 429: Not retried automatically; valid
Retry-Afterheader guidance takes precedence over the AIRS JSONretry_after.interval/unitfields and is exposed asretryAfterMs - Backoff: Exponential with full jitter (
uniform [0, 2^attempt × 1000ms]) - Max retries: Configurable 0-5, default 5
- Scanner per-call override: Pass
{ numRetries }to any Scanner operation;0means one total fetch attempt, and an omitted value preserves the global setting - 401/403 handling: OAuth2 clients refresh the token and retry at most once, outside the retry budget. An explicit SCM policy denial (
403withx-opa-decision: false) is not retried: refreshing the same identity cannot repair its permissions.
Every attempt has a 60-second deadline by default, including authentication waits and response-body
reads. Set PANW_AI_SEC_TIMEOUT_MS to a positive integer to change it across domains. Scanner calls
also accept { timeoutMs, signal }. The caller's abort reason is preserved; a deadline failure is
reported as a network failure. This is a per-attempt deadline, not an overall workflow deadline.
Backoff is cancellable, and server Retry-After delays used for automatic retries are capped at
60 seconds. A failed body read after a successful response never causes a POST replay.
For async POSTs, a terminal network error or 5xx response is an ambiguous outcome: AIRS may have
accepted the request. The SDK does not claim exactly-once submission and does not expose a generic
retryable flag because retry safety depends on the operation. Polling GETs are idempotent; async
submission is not known to be.
AI Gateway request validation
Every body-taking AI Gateway method validates its exported Zod request schema before OAuth token
preparation and before fetch. Invalid input therefore cannot consume a token request or send a
partial mutation. Error messages identify the HTTP operation and failing field paths without
including rejected values:
try {
await gw.configs.update(configId, { config: { retry: { attempts: -1 } } });
} catch (error) {
if (error instanceof AISecSDKException) {
console.log(error.errorType); // AISEC_USER_REQUEST_PAYLOAD_ERROR
console.log(error.message); // includes PUT /configs/<id> and the field path
}
}
Create requests reject unknown stable fields, and partial update requests reject {}. Typed JSON
extension points remain available for provider- and Portkey-specific settings; they reject
non-serializable values such as undefined, functions, NaN, and infinities.