Skip to content
main-compute

Reference

Errors

Error shapes, status codes and retry rules for the inference API.

Updated 2026-10-25 · MainAI Compute docs

Two envelopesLink to this section

/v1 errors use the OpenAI shape. /api errors use the portal shape. Both carry an x-request-id response header.

/v1 error
{
  "error": {
    "message": "Model 'mainai-cyber' is not enabled for this key.",
    "type": "permission_error",
    "param": null,
    "code": "model_not_allowed"
  }
}
/api error
{
  "error": {
    "code": "forbidden",
    "message": "You need the billing role.",
    "requestId": "req_01j9x7…"
  }
}

400

Meaning
Malformed JSON, missing field or invalid value.
Retry?
Fix the request.

401

Meaning
Missing, malformed, revoked or expired key.
Retry?
Fix credentials.

402

Meaning
Wallet or key budget exhausted.
Retry?
Top up or raise the limit.

403

Meaning
Model not allowed, identity/plan gate, organization suspended or CSRF failure.
Retry?
Depends; see code.

404

Meaning
Unknown model or /v1 path.
Retry?
Fix the model or path.

413

Meaning
Body over 8 MiB.
Retry?
Shrink or split.

429

Meaning
Rate or concurrency limit.
Retry?
Yes, with backoff.

500

Meaning
Unexpected portal error.
Retry?
Yes, bounded.

502/503/504

Meaning
Engine or routing unavailable.
Retry?
Yes, with backoff.

Stable MainAI codesLink to this section

invalid_api_key

Status
401
Cause
Header missing, wrong scheme, wrong prefix, revoked or expired key.

insufficient_credit

Status
402
Cause
Wallet balance or hard key budget exhausted.

org_suspended

Status
403
Cause
Organization suspended by an operator.

model_not_allowed

Status
403
Cause
Model outside the key allow-list.

kyc_required

Status
403
Cause
Identity is not approved yet.

contract_required

Status
403
Cause
KYC is approved but no Enterprise contract is recorded.

verification_required

Status
403
Cause
Compatibility code for an offer whose access tier rejects the caller.

model_not_found

Status
404
Cause
Model ID is not in the public or private catalog.

invalid_json

Status
400
Cause
Body is not parseable JSON.

payload_too_large

Status
413
Cause
Body exceeds 8 MiB.

not_found

Status
404
Cause
Path is not one of the proxied /v1 routes.

upstream_unavailable

Status
503
Cause
The inference route failed or refused the connection.

Passthrough codesLink to this section

Once a request reaches an engine, the upstream error is passed through with its status and OpenAI-style code. Common examples are context_length_exceeded, rate_limit_exceeded, invalid_request_error and server_error. Read error.message; expect provider wording.

RetriesLink to this section

  • Retry only 429, 500, 502, 503 and 504, and only when the request is safe to repeat.
  • Use exponential backoff with jitter, starting around 250 ms, capped at 30 s.
  • Honor Retry-After when present.
  • Cap attempts. Four is usually enough for interactive calls.
  • For streams, retry only if no content chunk has been emitted; otherwise the user has already seen partial output.
Bounded retry
async function callOnce(): Promise<Response> {
  return fetch(`https://cloud.mainai.dk/v1/chat/completions`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.MAINAI_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      model: "mainai-coder",
      messages: [{ role: "user", content: "Say ready" }],
      max_tokens: 8,
    }),
  });
}

async function callWithRetry() {
  for (let attempt = 0; attempt < 4; attempt++) {
    const res = await callOnce();
    if (![429, 500, 502, 503, 504].includes(res.status)) return res;

    const retryAfter = Number(res.headers.get("retry-after"));
    const wait = Number.isFinite(retryAfter) && retryAfter > 0
      ? retryAfter * 1000
      : 250 * 2 ** attempt + Math.random() * 200;
    await new Promise((resolve) => setTimeout(resolve, wait));
  }
  return callOnce();
}

Debugging checklistLink to this section

  1. 01Record status, error.code and x-request-id.
  2. 02Confirm the key prefix and that the key is active.
  3. 03Call GET /v1/models with the same key to see its allow-list.
  4. 04Check the body size and JSON validity.
  5. 05Check the wallet and organization status in the portal.
  6. 06Escalate with the request ID if the failure repeats without a local cause.

Rate limits · Authentication · API reference