Lunos logoLunos

Error Handling

All errors extend LunosError. HTTP errors are mapped to specific classes for precise handling.

Error Classes

import Lunos, {
  RateLimitError,
  AuthenticationError,
  APIError,
} from "@lunos/sdk";

try {
  await client.chat.completions.create({
    model: "openai/gpt-4o",
    messages: [{ role: "user", content: "Hello" }],
  });
} catch (err) {
  if (err instanceof RateLimitError) {
    // 429 — wait and retry
  } else if (err instanceof AuthenticationError) {
    // 401 — invalid API key
  } else if (err instanceof APIError) {
    console.error(`Error ${err.status}: ${err.message}`);
  }
}

Error Reference

Status Error Class When It Happens
400 BadRequestError Invalid request parameters
401 AuthenticationError Missing/invalid API key
403 PermissionDeniedError Insufficient permissions
404 NotFoundError Endpoint or resource not found
422 UnprocessableEntityError Valid JSON but semantic error
429 RateLimitError Too many requests
≥500 InternalServerError Server-side failure
APIConnectionError Network connectivity issue
APIConnectionTimeoutError Request exceeded timeout

Automatic Retries

Transient failures (408, 409, 429, ≥500, and network errors) are automatically retried with exponential backoff. Non-retryable errors (400, 401, 403, 404, 422) fail immediately.

// Disable retries globally
const client = new Lunos({ apiKey: "sk-...", maxRetries: 0 });

// Override per-request
await client.chat.completions.create(
  { model: "openai/gpt-4o", messages: [{ role: "user", content: "Hi" }] },
  { maxRetries: 5, timeout: 120_000 },
);

Retry Behavior

The SDK uses exponential backoff with the formula:

delay = min(500ms × 2^attempt, 8000ms)
Attempt Delay
1st retry 500ms
2nd retry 1000ms
3rd retry 2000ms
4th retry 4000ms
5th+ retry 8000ms (max)

Abort Signals

Cancel requests using AbortSignal:

const controller = new AbortController();

// Cancel after 5 seconds
setTimeout(() => controller.abort(), 5000);

try {
  await client.chat.completions.create(
    { model: "openai/gpt-4o", messages: [{ role: "user", content: "Hi" }] },
    { signal: controller.signal },
  );
} catch (err) {
  if (err instanceof APIConnectionTimeoutError) {
    console.log("Request was aborted");
  }
}