Normalized errors
Every provider maps transport and domain failures into stable classes. Branch on classes or codes, retain the provider context, and choose retry behavior deliberately.
Error hierarchy
| Class | Code | Typical response |
|---|---|---|
WorkAuthenticationError | authentication | Refresh or replace credentials; do not blind-retry. |
WorkAuthorizationError | authorization | Request scope/permission or remove the action. |
WorkNotFoundError | not_found | Verify target and visibility. |
WorkRateLimitError | rate_limit | Retry after the supplied delay with jitter. |
WorkConflictError | conflict | Re-read, prepare a new plan, request approval again. |
WorkUnsupportedError | unsupported | Change the tool schema or provider strategy. |
WorkValidationError | validation | Fix input; retrying unchanged input is wrong. |
WorkError | provider / network | Inspect cause and provider policy. |
Shared fields
error.code // stable WorkErrorCode
error.provider // github | linear | jira | azure-devops | custom
error.status // provider HTTP status when available
error.retryAfterMs // normalized delay for rate limits
error.details // parsed provider or validation context
error.cause // standard Error cause chainTyped handling
error-policy.ts
import {
WorkAuthenticationError,
WorkConflictError,
WorkRateLimitError,
WorkValidationError,
} from "work-sdk";
try {
return await work.commit(change, { idempotencyKey });
} catch (error) {
if (error instanceof WorkAuthenticationError) {
return refreshCredentials();
}
if (error instanceof WorkRateLimitError) {
return retryAfter(error.retryAfterMs);
}
if (error instanceof WorkConflictError) {
return prepareAgainAndRequestApproval();
}
if (error instanceof WorkValidationError) {
return rejectToolInput(error.details);
}
throw error;
}Retry policy
- Rate limit: retry after
retryAfterMs, add jitter, preserve the idempotency key. - Network: retry only with a stable idempotency key or reconciliation strategy.
- Conflict: never retry the same plan; prepare and approve again.
- Validation/unsupported: do not retry unchanged input.
- Authentication: refresh credentials before another attempt.
A timeout cannot prove whether the remote provider committed a write. Idempotency protects SDK-level replays when the first result was recorded; reconciliation is still needed for the narrow “provider succeeded, receipt persistence failed” window.
Logging and redaction
Log class, code, provider, status, retry delay, and a correlation ID. Treat details and cause as potentially sensitive because providers can echo field values or request context. Never log adapter options or authorization headers.