Errors
All SDK methods throw HybriDBError on failure. Always wrap calls in try/catch.
HybriDBError
typescript
import { HybriDBError } from '@hybridb/sdk';
try {
const decision = await hdb.requestDecision({ ... });
} catch (err) {
if (err instanceof HybriDBError) {
console.log(err.code); // HybriDBErrorCode
console.log(err.message); // human-readable description
console.log(err.status); // HTTP status code
} else {
throw err; // unexpected error — rethrow
}
}Error codes
Auth errors
| Code | Status | Meaning |
|---|---|---|
UNAUTHORIZED | 401 | Missing or invalid API key / token |
FORBIDDEN | 403 | Valid credentials but insufficient scope |
TOKEN_EXPIRED | 401 | JWT has expired — refresh and retry |
Decision errors
| Code | Status | Meaning |
|---|---|---|
POLICY_DENIED | 403 | Decision outcome was blocked |
DECISION_NOT_FOUND | 404 | Decision ID does not exist |
DECISION_ALREADY_CONSUMED | 409 | Decision was already used to trigger a pipeline |
DECISION_ESCALATED | 202 | Decision requires human review before execution |
Pipeline errors
| Code | Status | Meaning |
|---|---|---|
PIPELINE_NOT_FOUND | 404 | No pipeline with that name or ID exists |
PIPELINE_STEP_FAILED | 500 | One or more steps failed during execution |
CIRCUIT_BREAKER_OPEN | 503 | Pipeline circuit breaker is tripped |
EXECUTION_NOT_FOUND | 404 | Execution ID does not exist |
Reversibility errors
| Code | Status | Meaning |
|---|---|---|
ROLLBACK_WINDOW_EXPIRED | 409 | Past the rollback window for this execution |
ROLLBACK_ALREADY_COMPLETED | 409 | This execution was already rolled back |
CHECKPOINT_NOT_FOUND | 404 | Checkpoint ID does not exist |
REPLAY_NOT_AVAILABLE | 409 | No checkpoints available to replay from |
Request errors
| Code | Status | Meaning |
|---|---|---|
VALIDATION_ERROR | 400 | Request body failed schema validation |
IDEMPOTENCY_CONFLICT | 409 | Same idempotency key used with different parameters |
RATE_LIMITED | 429 | Too many requests — back off and retry |
NOT_FOUND | 404 | Resource does not exist |
Server errors
| Code | Status | Meaning |
|---|---|---|
INTERNAL_ERROR | 500 | Unexpected server error |
SERVICE_UNAVAILABLE | 503 | hybriDB temporarily unavailable |
Retry strategy
The SDK retries automatically on 5xx and 429 errors (default: 3 attempts, 500ms delay). Configure via the constructor:
typescript
const hdb = new HybriDBClient({
baseUrl: 'https://hybridb.stellrai.com',
apiKey: process.env.HDB_API_KEY!,
retries: 5, // retry up to 5 times
retryDelay: 1_000, // 1 second between retries
});Do not retry on 4xx errors (except 429) — they indicate a client problem that won't resolve with retries.
Full error handling pattern
typescript
import { HybriDBClient, HybriDBError } from '@hybridb/sdk';
async function processPayment(actorId: string, amount: number) {
let decision;
try {
decision = await hdb.requestDecision({
decisionType: 'payment.authorize',
action: 'payment.initiate',
inputData: { actorId, amount },
});
} catch (err) {
if (err instanceof HybriDBError) {
if (err.code === 'RATE_LIMITED') {
// The SDK retries automatically — if we're here, retries exhausted
throw new Error('Service temporarily unavailable — try again shortly');
}
}
throw err;
}
if (decision.outcome === 'blocked') {
// Not an error — a valid policy decision
return { allowed: false, reason: decision.rationale };
}
if (decision.outcome === 'escalated') {
await queueForReview(decision.decisionId);
return { allowed: false, reason: 'Pending review' };
}
try {
const execution = await hdb.triggerPipelineByName('payment.execute.standard', {
decisionId: decision.decisionId,
input: { amount, actorId },
});
return { allowed: true, executionId: execution.id };
} catch (err) {
if (err instanceof HybriDBError && err.code === 'PIPELINE_STEP_FAILED') {
// Execution failed — Stellrai auto-compensates, check status
const exec = await hdb.getPipelineExecution(err.executionId);
console.error('Pipeline failed, status:', exec.status);
}
throw err;
}
}