> ## Documentation Index
> Fetch the complete documentation index at: https://evalgate.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Errors

# API error codes and HTTP status mapping

> Every EvalGate error code, its HTTP status, what it means, and how to handle errors in TypeScript and Python with try/catch examples.

When a request fails, EvalGate always returns a JSON object in the same envelope shape — regardless of the HTTP status code. Parsing this envelope lets you handle every error class in a single place.

## Error envelope

Every error response has this structure:

```json theme={null} theme={null}
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "name is required",
    "requestId": "550e8400-e29b-41d4-a716-446655440000"
  }
}
```

**error.code** `string`

A machine-readable constant identifying the error class. Use this field for programmatic error handling — never parse `message`.

**error.message** `string`

A human-readable description of what went wrong. Suitable for logs and development debugging; do not display this to end users without filtering.

**error.details** `unknown`

Optional additional context, omitted when there is none. For `VALIDATION_ERROR`, this describes which fields failed and why; other codes may include structured context such as per-judge failure codes.

**error.requestId** `string`

A UUID that uniquely identifies the request on EvalGate's servers. Include this value in any support ticket — the team can use it to locate the exact request in logs. The same UUID appears in the `x-request-id` response header.

## Error codes and HTTP status mapping

| Code | HTTP status | When it occurs |
| - | - | - |
| `UNAUTHORIZED` | 401 | Missing or invalid API key |
| `FORBIDDEN` | 403 | Key lacks required scope for this resource |
| `NO_ORG_MEMBERSHIP` | 403 | Authenticated user is not a member of the target organization |
| `QUOTA_EXCEEDED` | 403 | Organization has reached a usage limit (upgrade required) |
| `FEATURE_LIMIT_REACHED` | 403 | Plan feature limit reached |
| `PUBLIC_SHARING_DISABLED` | 403 | Public sharing is turned off for this organization |
| `NOT_FOUND` | 404 | Resource does not exist, or the ID belongs to a different organization |
| `METHOD_NOT_ALLOWED` | 405 | HTTP method not supported on this route |
| `VALIDATION_ERROR` | 400 | Request body or query parameters failed schema validation |
| `PROVIDER_KEY_MISSING` | 400 | No BYOK provider key is configured for the requested provider |
| `PROVIDER_KEY_EXPIRED` | 400 | The stored provider key has expired |
| `CONFLICT` | 409 | A resource with the same identifier already exists |
| `INVALID_REFERENCE` | 409 | The request references a resource that does not exist |
| `SHARE_REVOKED`, `SHARE_EXPIRED`, `SHARE_UNAVAILABLE` | 410 | The share link is no longer available |
| `PAYLOAD_TOO_LARGE` | 413 | Request body exceeds the size limit |
| `RATE_LIMITED` | 429 | Too many requests — honor `Retry-After` or the `RateLimit` reset delay |
| `PROVIDER_RATE_LIMITED` | 429 | Your model provider rate-limited the call |
| `PROVIDER_UNAUTHORIZED` | 401 | Your model provider rejected the BYOK credential |
| `INTERNAL_ERROR` | 500 | Unexpected server error — include the `requestId` when contacting support |
| `SERVICE_UNAVAILABLE` | 503 | EvalGate is temporarily unavailable — retry with exponential backoff |
| `PROVIDER_UNAVAILABLE` | 503 | Your model provider is unavailable |

Agent handoff routes also return `AGENT_HANDOFF_INVALID` (400), `AGENT_HANDOFF_DENIED` (403), and `AGENT_HANDOFF_EXPIRED` / `AGENT_HANDOFF_CONSUMED` (410).

> [!NOTE]
>
> `QUOTA_EXCEEDED`, `FEATURE_LIMIT_REACHED`, and `NO_ORG_MEMBERSHIP` all map to HTTP 403. Distinguish them by the `code` field, not the status code.

## Handling errors in code

```typescript TypeScript theme={null} theme={null}
import { AIEvalClient } from '@evalgate/sdk';

const client = AIEvalClient.init();

try {
  const evaluation = await client.evaluations.create({
    name: 'My eval',
    type: 'unit_test',
  });
  console.log('Created:', evaluation.id);
} catch (err: unknown) {
  if (err instanceof Error && 'code' in err) {
    const apiErr = err as { code: string; message: string; requestId?: string };
    switch (apiErr.code) {
      case 'UNAUTHORIZED':
        console.error('Check your EVALGATE_API_KEY environment variable.');
        break;
      case 'RATE_LIMITED':
        console.error('Rate limit hit — retrying after backoff.');
        break;
      case 'VALIDATION_ERROR':
        console.error('Invalid request:', apiErr.message);
        break;
      default:
        console.error(`API error ${apiErr.code}: ${apiErr.message}`);
        console.error('Request ID for support:', apiErr.requestId);
    }
  } else {
    throw err;
  }
}
```

```python Python theme={null} theme={null}
import os
import requests

BASE_URL = "https://evalgate.com"
HEADERS = {
    "Authorization": f"Bearer {os.environ['EVALGATE_API_KEY']}",
    "Content-Type": "application/json",
}

response = requests.post(
    f"{BASE_URL}/api/evaluations",
    headers=HEADERS,
    json={"name": "My eval", "type": "unit_test"},
)

if not response.ok:
    body = response.json()
    error = body.get("error", {})
    code = error.get("code")
    request_id = error.get("requestId")

    if code == "UNAUTHORIZED":
        raise RuntimeError("Check your EVALGATE_API_KEY environment variable.")
    elif code == "RATE_LIMITED":
        raise RuntimeError("Rate limit hit — back off and retry.")
    elif code == "VALIDATION_ERROR":
        raise ValueError(f"Invalid request: {error.get('message')}")
    else:
        raise RuntimeError(
            f"API error {code}: {error.get('message')} (requestId: {request_id})"
        )

data = response.json()
print("Created:", data["id"])
```

> [!TIP]
>
> When retrying after a `429 RATE_LIMITED` response, honor `Retry-After` first.
> Otherwise read the `t` parameter from the structured `RateLimit` header or
> the compatibility `X-RateLimit-Reset` timestamp. The TypeScript SDK handles
> this automatically with exponential backoff.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.