---
title: Error Codes Reference
path: reference/error-codes
status: published
---

# Error Codes Reference

Complete taxonomy of error codes ScaiGrid returns. For the envelope shape and retry classification, see [Errors](../03-core-concepts/07-errors.md).

## Envelope

Every error response has the shape:

```json
{
  "status": "error",
  "error": {
    "code": "...",
    "message": "...",
    "retry_after": 30,
    "details": [{"field": "...", "message": "..."}]
  },
  "meta": {"request_id": "req_..."}
}
```

`code` is the machine-readable identifier. Branch on it.

## Authentication and authorization

| Code | HTTP | Meaning |
|------|------|---------|
| `AUTH_TOKEN_MISSING` | 401 | No Authorization header |
| `AUTH_TOKEN_INVALID` | 401 | Invalid or expired token |
| `AUTH_INSUFFICIENT_SCOPE` | 403 | Token lacks a required scope |
| `AUTHZ_PERMISSION_DENIED` | 403 | User lacks required permission |
| `AUTH_FLOW_INVALID` | 401 | OAuth flow state invalid/expired |
| `AUTH_IDENTITY_NOT_FOUND` | 404 | No account for this email |
| `SESSION_EXPIRED` | 401 | Token expired, refresh required |
| `SERVICE_TOKEN_INVALID` | 401 | Invalid service token |

## Validation

| Code | HTTP | Meaning |
|------|------|---------|
| `VALIDATION_ERROR` | 422 | Request body didn't match schema. `details` array has per-field issues |
| `SLUG_CONFLICT` | 409 | Resource slug already exists |

## Models and backends

| Code | HTTP | Meaning |
|------|------|---------|
| `MODEL_NOT_FOUND` | 404 | No frontend model with that slug |
| `MODEL_ACCESS_DENIED` | 403 | Model exists but not enabled for tenant |
| `MODEL_UNAVAILABLE` | 503 | All backends for this model are unhealthy |
| `BACKEND_NOT_FOUND` | 404 | Backend doesn't exist |
| `BACKEND_ERROR` | 502 | Upstream provider returned an error |
| `BACKEND_TIMEOUT` | 504 | Upstream didn't respond in time |
| `BACKEND_RATE_LIMITED` | 429 | Upstream rate-limited us. `retry_after` present |
| `UPSTREAM_SHAPE_MISMATCH` | 502 | Upstream sent a response our parsers didn't accept |

## Providers

| Code | HTTP | Meaning |
|------|------|---------|
| `PROVIDER_NOT_FOUND` | 404 | Provider doesn't exist |
| `PROVIDER_DISCOVERY_ERROR` | 502 | Failed to discover models from provider |
| `PROVIDER_HAS_BACKENDS` | 409 | Can't delete provider with active backends |

## Rate limits and quotas

| Code | HTTP | Meaning |
|------|------|---------|
| `RATE_LIMITED` | 429 | ScaiGrid's own rate limiter. `retry_after` present |
| `QUOTA_EXCEEDED` | 429 | Hard quota reached |
| `BUDGET_EXCEEDED` | 429 | Usage budget exceeded |
| `BUDGET_NOT_FOUND` | 404 | Budget doesn't exist |

## Tenancy

| Code | HTTP | Meaning |
|------|------|---------|
| `PARTNER_NOT_FOUND` | 404 | |
| `TENANT_NOT_FOUND` | 404 | |
| `TENANT_SUSPENDED` | 403 | Tenant is administratively suspended |
| `PARTNER_SUSPENDED` | 403 | Partner is administratively suspended |

## Modules

| Code | HTTP | Meaning |
|------|------|---------|
| `MODULE_NOT_FOUND` | 404 | |
| `MODULE_NOT_ENABLED` | 403 | Module disabled for tenant |
| `MODULE_DEPENDENCY_UNAVAILABLE` | 424 | Required dependency module unavailable |

## Resources

| Code | HTTP | Meaning |
|------|------|---------|
| `USER_NOT_FOUND` | 404 | |
| `API_KEY_NOT_FOUND` | 404 | |
| `GROUP_NOT_FOUND` | 404 | |
| `GROUP_ROLE_NOT_FOUND` | 404 | |
| `TENANT_TEMPLATE_NOT_FOUND` | 404 | |
| `MODULE_PERMISSION_NOT_FOUND` | 404 | |
| `CUSTOM_ROLE_NOT_FOUND` | 404 | |
| `ROUTING_POLICY_NOT_FOUND` | 404 | |
| `MODEL_ACCESS_NOT_FOUND` | 404 | |
| `MODEL_GROUP_NOT_FOUND` | 404 | |
| `BATCH_NOT_FOUND` | 404 | |
| `SESSION_NOT_FOUND` | 404 | |
| `ROOM_NOT_FOUND` | 404 | |
| `ROOM_MEMBER_NOT_FOUND` | 404 | |
| `ROOM_ACCESS_DENIED` | 403 | Caller not a room member |
| `RESPONSE_NOT_FOUND` | 404 | OAI Responses API |
| `WEBHOOK_NOT_FOUND` | 404 | |
| `CHECKPOINT_NOT_FOUND` | 404 | |
| `CHECKPOINT_ALREADY_RESOLVED` | 409 | |
| `CHECKPOINT_ASSIGNEE_DENIED` | 403 | User not authorized to resolve |

## Delegation

| Code | HTTP | Meaning |
|------|------|---------|
| `DELEGATION_INVALID` | 400 | Delegation scopes exceed user's own permissions |

## Inference infrastructure

| Code | HTTP | Meaning |
|------|------|---------|
| `INFERENCE_NODE_NOT_FOUND` | 404 | ScaiInfer node doesn't exist |
| `NODE_NOT_ONLINE` | 409 | Node must be online for this command |
| `NODE_UNAVAILABLE` | 502 | Could not connect to node |
| `REGISTRY_NOT_AVAILABLE` | 501 | Node doesn't support registry browsing |

## Cores (ScaiCore)

| Code | HTTP | Meaning |
|------|------|---------|
| `CORE_NOT_FOUND` | 404 | |

## Webhooks

| Code | HTTP | Meaning |
|------|------|---------|
| `WEBHOOK_VERIFICATION_ERROR` | 401 | Inbound webhook signature verification failed |

## Service state

| Code | HTTP | Meaning |
|------|------|---------|
| `SERVICE_DRAINING` | 503 | Gateway is shutting down; retry shortly |
| `SERVICE_UNAVAILABLE` | 503 | A dependency (Redis, MariaDB) is down |

## Module-specific errors

Module errors follow `{MODULE}_{NAME}` convention:

- ScaiBot: `SCAIBOT_BOT_NOT_FOUND`, `SCAIBOT_CONVERSATION_NOT_FOUND`, etc.
- ScaiQueue: `SCAIQUEUE_MESSAGE_NOT_FOUND`, `SCAIQUEUE_CLAIM_INVALID`, etc.
- ScaiBunker: `BUNKER_NOT_FOUND`, `BUNKER_NOT_RUNNING`, `BUNKER_QUOTA_EXCEEDED`, `BUNKER_TRANSITION_ERROR`, `WORKER_UNAVAILABLE`, `NO_SUITABLE_WORKER`, `IMAGE_NOT_FOUND`, `BRIDGE_NOT_FOUND`, `AVAILABILITY_GROUP_NOT_FOUND`, `QUOTA_PROFILE_NOT_FOUND`, `QUOTA_ASSIGNMENT_CONFLICT`, `LIFECYCLE_MODE_DENIED`, `NETWORK_PROFILE_DENIED`, `PEERS_BAD_SHA`, `PEERS_MISSING_WORKER_HEADER`, etc.
- ScaiMatrix: `COLLECTION_NOT_FOUND`, `DOCUMENT_NOT_FOUND`, etc.
- ScaiMind: `TRAINING_JOB_NOT_FOUND`, `EVALUATION_NOT_FOUND`, etc.
- ScaiPersona: `PERSONA_NOT_FOUND`, `PERSONA_NOT_PUBLISHED`, etc.
- ScaiSkills: `SKILL_NOT_FOUND`, `SKILL_VERSION_YANKED`, etc.
- ScaiLink: `SCAILINK_SESSION_NOT_FOUND`, `SCAILINK_CAPABILITY_DENIED`, etc.

See each module's documentation for its specific codes.

## Sync

| Code | HTTP | Meaning |
|------|------|---------|
| `SYNC_ERROR` | 502 | Failed to sync from ScaiKey |

## Generic fallback

| Code | HTTP | Meaning |
|------|------|---------|
| `INTERNAL_ERROR` | 500 | Unexpected server-side error. Always report with request ID |

## Related

- [Errors (concepts)](../03-core-concepts/07-errors.md) — envelope shape, retry logic
- [Your First Integration](../02-getting-started/03-your-first-integration.md) — error-handling code examples
