Errors
The error body the Gigadrive Network API returns, what each status code means, and which failures are worth retrying.
Every failure on a resource endpoint returns the same object: one error field holding a human-readable message. There is no machine-readable code to switch on, so branch on the HTTP status and log the message.
{
"error": "Access denied: You do not have permission to access this application"
}Status codes
| Status | What happened | What to do |
|---|---|---|
| 400 | The handler rejected a value the schema could not catch, such as an unknown scope name or a root directory containing .. | Fix the value. The same request will keep failing |
| 401 | The bearer token is expired, unrecognised, or its API key was revoked | Exchange the key for a fresh token and retry once |
| 402 | Creating a deployment was refused: the organization reached its billing cap, or used up the compute included in this period | Raise the budget or change the plan |
| 403 | Either the token lacks the required scope, or the actor may not reach that resource | Read the message, then check Scopes |
| 404 | The resource does not exist, or it exists and belongs to someone else | Do not read this as proof of absence |
| 409 | The write conflicts with existing state: a duplicate name, a taken hostname, a bucket that still holds objects, a restore onto a key already in use | Resolve the conflict, then retry |
| 422 | The request failed schema validation before reaching the handler | Fix the shape. The body names the offending field |
| 429 | A request throttle, a plan quota, or an upstream AI provider limit | See Rate limits |
| 500 | An unhandled failure in the API | Retry with backoff |
| 502 | A storage provider call failed | Retry with backoff |
| 503 | Something the endpoint depends on is temporarily unavailable | Retry with backoff |
Validation failures
A body, query string or header that does not match the endpoint's schema is rejected before the handler runs. That response is 422 and does not use the single-field shape:
{
"type": "validation",
"on": "body",
"property": "/name",
"message": "Expected string",
"summary": "Expected property 'name' to be string but found: 123"
}on tells you where to look: body, query, params or headers. The full response also carries expected, found, and an errors array with one entry per failing field.
A missing Authorization header returns 422, not 401
The header is validated against the pattern Bearer <token> by the same schema layer, ahead of authentication.
Omit it, or send Token abc, and you get a 422 with "on": "headers". A well-formed header carrying a bad
token is what produces a 401.
Authentication failures
A 401 also carries a WWW-Authenticate header naming the OAuth error code:
WWW-Authenticate: Bearer error="invalid_token", error_description="Invalid network or IDP token"The JSON body repeats only the description, in its error field. invalid_token covers a signature that does not verify, an expired token, a deleted API key, an expired API key, and a key whose actor no longer exists.
POST /oauth2/token is the exception to all of this and answers in the RFC 6749 shape, with both error and error_description. Authentication lists the descriptions it returns.
Not found and access denied
An endpoint that resolves an application, deployment or organization collapses a genuine miss and a lookup failure into the same 404, including a malformed UUID. That is deliberate: it keeps the API from confirming that a resource exists in someone else's organization.
A 403 Access denied appears when the actor is known and is known to be outside the resource. Both mean the same thing from the caller's side, so handle them together.
AI Gateway errors
The AI Gateway inference endpoints are OpenAI-compatible, errors included, so they nest an object under error instead of a string:
| Field | Contents |
|---|---|
message | Human-readable gateway or provider message |
type | OpenAI-compatible error category |
param | The request parameter at fault, when known |
code | Machine-readable code, when known |
Retrying
Only three statuses can succeed on an unchanged retry: 500, 502 and 503. Back off exponentially with jitter on those.
Retry a 429 after the delay in Retry-After, and only when the response actually carries that header. Retry a 401 exactly once, after refetching the token; a second 401 means the credential is wrong rather than stale. Everything else in the 4xx range will fail identically forever, so surface it instead of looping.
In the SDK
@gigadrive/sdk throws ApiError for any non-2xx, carrying .status and taking .message from the body's error field. It handles the 401 retry for you, then throws AuthenticationError if the second attempt fails too. A request whose body is a ReadableStream is never retried, because the body cannot be replayed.
import { ApiError, GigadriveClient } from '@gigadrive/sdk';
const client = new GigadriveClient();
try {
const deployment = await client.deployments.get('0197b2f1-2f4a-7a0b-8a2d-222222222222');
console.log(deployment.status);
} catch (error) {
if (error instanceof ApiError && error.status === 404) {
console.error('No such deployment, or it belongs to another organization');
} else {
throw error;
}
}