Error Codes
All API errors follow a consistent format with a machine-readable code, human-readable message, and a request ID for debugging.
Error Response Format
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Field 'prompt' is required",
"details": {
"field": "prompt",
"rule": "required"
}
},
"meta": {
"requestId": "req_abc123def456",
"timestamp": "2026-02-20T10:00:00Z"
}
}HTTP Status Codes
| Status | Meaning | When |
|---|---|---|
200 | OK | Successful GET, PATCH, DELETE |
201 | Created | Successful POST (task/plan/template creation) |
400 | Bad Request | Invalid input, missing required fields |
401 | Unauthorized | Missing or invalid authentication |
403 | Forbidden | Insufficient permissions for the requested action |
404 | Not Found | Resource does not exist |
409 | Conflict | Duplicate idempotency key or resource conflict |
422 | Unprocessable Entity | Valid JSON but semantically invalid (e.g., circular deps) |
429 | Too Many Requests | Rate limit exceeded |
500 | Internal Server Error | Unexpected server error |
502 | Bad Gateway | Temporal or upstream service unavailable |
503 | Service Unavailable | API is temporarily overloaded or in maintenance |
504 | Gateway Timeout | Upstream request timed out |
Error Codes Reference
Authentication Errors (401, 403)
| Code | Message | Resolution |
|---|---|---|
AUTH_REQUIRED | Authentication is required | Include Authorization header |
AUTH_INVALID_TOKEN | The provided token is invalid | Check token format and validity |
AUTH_TOKEN_EXPIRED | The authentication token has expired | Refresh the token or re-authenticate |
AUTH_INSUFFICIENT_PERMISSIONS | You do not have permission for this action | Check your role's permission set |
AUTH_INVALID_API_KEY | The API key is invalid or revoked | Generate a new API key |
Validation Errors (400, 422)
| Code | Message | Resolution |
|---|---|---|
VALIDATION_ERROR | Input validation failed | Check the details.field for the specific issue |
INVALID_MODEL | The specified model is not available | Use a supported model identifier |
INVALID_QUEUE | The specified queue does not exist | Check available queues |
CIRCULAR_DEPENDENCY | Plan contains circular step dependencies | Review dependsOn fields in your steps |
MISSING_DEPENDENCY | Step references a non-existent dependency | Check that all dependsOn IDs match step IDs |
INVALID_TEMPLATE_SCHEMA | Template input schema is invalid | Validate against JSON Schema spec |
DUPLICATE_STEP_ID | Two steps share the same ID | Use unique IDs for each step |
Resource Errors (404, 409)
| Code | Message | Resolution |
|---|---|---|
NOT_FOUND | The requested resource was not found | Verify the resource ID |
TASK_NOT_FOUND | Task with the given ID does not exist | Check the task ID |
PLAN_NOT_FOUND | Plan with the given ID does not exist | Check the plan ID |
TEMPLATE_NOT_FOUND | Template with the given ID does not exist | Check the template ID |
EXECUTION_NOT_FOUND | Execution with the given ID does not exist | Check the execution ID |
IDEMPOTENCY_CONFLICT | A request with this idempotency key already exists | Use a different key or retry the original |
Task Execution Errors
| Code | Message | Resolution |
|---|---|---|
TASK_TIMEOUT | Task execution timed out | Increase timeoutMs or simplify the prompt |
TASK_CANCELLED | Task was cancelled by user | Not an error; expected cancellation |
MODEL_UNAVAILABLE | The requested model is temporarily unavailable | Retry or use a fallback model |
MODEL_RATE_LIMIT | Model provider rate limit hit | Wait and retry; the SDK handles this automatically |
WORKER_UNAVAILABLE | No workers available for the specified queue | Check worker health and queue configuration |
CONTEXT_TOO_LARGE | Input exceeds the model's context window | Reduce input size or use a model with larger context |
HITL Errors
| Code | Message | Resolution |
|---|---|---|
HITL_NOT_PENDING | Task is not in awaiting_approval status | Check task status before approving |
HITL_ALREADY_REVIEWED | Task has already been approved or rejected | No action needed |
HITL_TIMEOUT | HITL review period has expired | Task was auto-escalated or auto-rejected |
HITL_INVALID_REVIEWER | The reviewer ID is not authorized | Check reviewer permissions |
Rate Limiting (429)
| Code | Message | Resolution |
|---|---|---|
RATE_LIMIT_EXCEEDED | Too many requests | Wait for Retry-After seconds |
Response includes:
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Try again in 12 seconds.",
"details": {
"limit": 300,
"remaining": 0,
"resetAt": "2026-02-20T10:01:00Z",
"retryAfterMs": 12000
}
}
}Server Errors (500, 502, 503)
| Code | Message | Resolution |
|---|---|---|
INTERNAL_ERROR | An unexpected error occurred | Contact support with the requestId |
TEMPORAL_UNAVAILABLE | Cannot connect to Temporal server | Check Temporal server health |
DATABASE_ERROR | Database connection or query error | Check PostgreSQL health |
SERVICE_OVERLOADED | API is temporarily overloaded | Retry with exponential backoff |
Error Handling Best Practices
SDK Error Handling
import {
DevTeamError,
AuthError,
TimeoutError,
ValidationError,
RateLimitError,
NotFoundError,
} from 'devteam-sdk';
try {
const task = await client.createTask({ prompt: '...' });
} catch (error) {
if (error instanceof AuthError) {
// Re-authenticate
await client.refreshToken();
} else if (error instanceof RateLimitError) {
// Wait and retry
await new Promise((r) => setTimeout(r, error.retryAfterMs));
} else if (error instanceof ValidationError) {
// Fix input
console.error('Invalid fields:', error.fields);
} else if (error instanceof TimeoutError) {
// Task is still running; just the wait timed out
console.log('Task still running, check later');
} else if (error instanceof NotFoundError) {
console.error(`${error.resource} ${error.resourceId} not found`);
} else if (error instanceof DevTeamError) {
// Generic API error
console.error(`Error ${error.code}: ${error.message}`);
console.error(`Request ID: ${error.requestId}`);
}
}Retry Logic
The SDK implements automatic retries for transient errors:
Retryable: 429, 500, 502, 503, 504, network errors
Not retryable: 400, 401, 403, 404, 409, 422// Custom retry configuration
const client = new DevTeamClient({
maxRetries: 5,
retryBackoff: {
initialMs: 1000,
multiplier: 2,
maxMs: 30000,
},
});Always include the requestId from error responses when contacting support. This allows rapid identification of the specific request in server logs.
Next Steps
- API Overview -- Full endpoint reference
- SDK Error Types -- TypeScript error class definitions