Skip to main content
When the BabySea API encounters an error, it returns an appropriate HTTP status code along with a structured JSON response to help you identify and resolve the issue.

Error Response Format

A standard error response follows this schema:
{
  "status": "error",
  "request_id": "req_123456789",
  "error": {
    "code": "BSE2001",
    "type": "invalid_input",
    "message": "The request body contains invalid parameters.",
    "retryable": false,
    "details": {
      "field": "generation_prompt"
    }
  }
}
  • code: A strict, non-changing alphanumeric code starting with BSE. Use this for programmatic error handling.
  • type: A snake_case, human-readable categorization of the error.
  • message: A detailed, human-readable message about what went wrong.
  • retryable: A boolean indicating if the exact same request might succeed on a subsequent attempt.
  • details: (Optional) Additional context related to the error.
  • provider_errors: (Optional) Present when an upstream failover chain is exhausted, indicating each individual provider’s specific failure reason.

Schema Validation Rejections

BabySea routes all requests through strict edge schema validation. Requests must exactly match one of our 45 documented operations (15 endpoints mapped across 3 regions: api.us, api.eu, api.jp). If your request pattern—URL path, parameter format, or method—deviates from our OpenAPI schema, our edge network intercepts it before orchestration. In such cases, you will receive a standard 403 Forbidden firewall rejection rather than a canonical JSON BSE... code layout. Ensure your integrations exactly mimic the documented schema.

Error Codes

Errors are grouped into five categories by prefix. If you need the policy context behind safety-filter or prohibited-use errors, see the AI principles and AI service terms on the BabySea Terms site. BSE1xxx - Authentication & Authorization
CodeTypeHTTPRetryableDescription
BSE1001authentication_required401NoMissing API key
BSE1002authentication_failed401NoInvalid API key
BSE1003insufficient_permissions403NoAPI key lacks permission for this resource
BSE1004insufficient_credits402NoNot enough credits for this generation
BSE1005rate_limit_exceeded429YesPer-account rate limit exceeded, check rateLimit.retryAfter
BSE1006auth_rate_limited429YesToo many requests from this IP (pre-auth)
BSE1007ip_not_allowed403NoIP not in API key allowlist
BSE1008account_not_found404NoAccount associated with this key was not found
BSE2xxx - Input Validation
CodeTypeHTTPRetryableDescription
BSE2001invalid_input400NoInvalid request parameters
BSE2002file_too_large422NoInput file exceeds maximum allowed dimensions
BSE2003file_too_small422NoInput file below minimum required dimensions
BSE2004unsupported_file_format422NoFile format not supported (JPEG, PNG, WebP only)
BSE2005file_load_error422NoFailed to load or process the provided file
BSE2006content_policy_violation422NoInput flagged by content safety filter
BSE2007file_size_exceeded422NoFile exceeds maximum allowed size in bytes
BSE2008parameter_out_of_range422NoA parameter value is outside the allowed range
BSE2009file_download_error422NoFailed to download file from URL (must be public)
BSE2010request_body_too_large413NoRequest body exceeds 100 KB
BSE2011generation_not_found404NoGeneration ID not found or not owned by this account
BSE2012generation_not_cancelable409NoGeneration already completed, failed, or canceled
BSE2013generation_cancel_window_expired409NoReserved cancel-window code. Current cancel conflicts typically surface as BSE2012
BSE3xxx - Model/Configuration
CodeTypeHTTPRetryableDescription
BSE3001model_not_found404NoUnknown model identifier
BSE3002model_not_configured500NoModel exists but is not properly configured
BSE3003feature_not_supported422NoFeature or parameter combination not supported by this model
BSE4xxx - Provider/Upstream
CodeTypeHTTPRetryableDescription
BSE4001provider_timeout504YesProvider did not respond within the time limit
BSE4002provider_out_of_memory502YesModel ran out of memory on the provider
BSE4003all_providers_failed502YesAll providers failed, failover exhausted
BSE4004provider_internal_error502YesProvider encountered an internal error
BSE4005provider_unavailable503YesProvider temporarily unavailable
BSE4006prediction_canceled409NoPrediction was canceled before completion
BSE4007provider_health_check_failed502YesModel failed its health check on the provider
BSE4008provider_start_error502YesProvider failed to start the prediction
BSE4009provider_upload_failed502YesFile upload to the provider failed
BSE5xxx - Internal Server
CodeTypeHTTPRetryableDescription
BSE5001internal_server_error500NoUnexpected internal error
BSE5002database_error500NoDatabase read/write failure
BSE5003storage_error500NoFile storage read/write failure

Auto-retry behavior

The SDK automatically retries errors where retryable evaluates to true (the SDK inspects this field on the payload, rather than strictly relying on HTTP status codes):
  • Default configuration: 2 retries (3 total execution attempts).
  • Retryable errors: Rate limit saturation (BSE1005, BSE1006) and the majority of upstream provider transient failures (BSE4001, BSE4002, BSE4003, BSE4004, BSE4005, BSE4007, BSE4008, BSE4009).
  • Non-retryable errors: Authentication, input validation, model configuration, and internal server faults are never retried.
  • Backoff logic: Respects the Retry-After header on 429 responses, utilizing exponential backoff for other retryable classes.

Provider failover behavior

When a retryable upstream provider error occurs and the selected model supports multiple providers, BabySea executes automated failover routing. If every attempted provider in the routing chain fails, the API ultimately surfaces an upstream exhaustion error (e.g., BSE4003).
TypeScript
// Disable retries
const client = new BabySea({ apiKey: 'bye_...', region: 'us', maxRetries: 0 });

// More retries for batch jobs
const client = new BabySea({ apiKey: 'bye_...', region: 'us', maxRetries: 5 });

Rate limit headers

Rate limit headers are included on every response:
HeaderDescription
X-RateLimit-LimitMaximum requests per window
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp when the window resets
Retry-AfterSeconds to wait (only on 429 responses)

Troubleshooting common errors

”insufficient_credits” (BSE1004)

What happened: Your account doesn’t have enough credits for this generation. Solutions:
  • Check your balance: await client.billing()
  • Estimate cost first: await client.estimate(model, count)
  • Purchase credits from Credit packs or upgrade your plan

”all_providers_failed” (BSE4003)

What happened: Every provider attempted for this model and payload combination failed. The exact provider chain executed depends on the model configuration and your generation_provider_order override. Solutions:
  • The SDK executed retries automatically (verify your maxRetries configuration).
  • Check provider status using client.health.providers() - see Provider health.
  • Attempt routing through a different model or provider order.

”generation_not_found” (BSE2011)

What happened: The generation ID doesn’t exist or isn’t owned by your account. Solutions:
  • Verify the generation_id - it should be a UUID
  • Make sure you’re using the correct API key
  • Generations are deleted if they fail billing checks

Cancel conflicts and late completion

What happened: You attempted to cancel a generation, but it completed or otherwise became non-cancelable before the cancel update was applied. What to expect:
  • The current public cancellation flow typically returns BSE2012 (generation_not_cancelable).
  • Fast generations may finalize before the cancellation signal is processed.
  • A successful generation remains charged even if the cancellation request arrived marginally too late.
Solutions:
  • Treat cancellation as a best-effort signal for in-flight generations.
  • Evaluate the generation status before retrying cancellation or deletion mutations.
  • Utilize webhooks so your architecture can react instantaneously to completions.

”rate_limit_exceeded” (BSE1005)

What happened: Your account exceeded the request rate limit for your plan. Solutions:
  • Wait for the window to reset (see X-RateLimit-Reset header)
  • The SDK respects Retry-After and retries automatically by default
  • Upgrade your plan for higher rate limits
  • Batch requests efficiently to avoid unnecessary calls

Authentication failures

CodeCauseFix
BSE1001Missing API keyEnsure apiKey is set in client config or env
BSE1002Invalid API keyVerify the key starts with bye_ and is not expired
BSE1007IP not allowedAdd your IP to the key’s allowlist or remove allowlist
BSE1008Account not foundThe associated account was deleted

Implementation with the SDK

If you are using the official Node.js / TypeScript SDK, the JSON error responses are automatically parsed and thrown as strongly-typed error classes.

Error classes

ClassWhen thrownKey properties
BabySeaErrorAPI returns non-2xxstatus, code, type, message, retryable, requestId, rateLimit, body
BabySeaTimeoutErrorRequest exceeds timeoutmessage
BabySeaRetryErrorAll retry attempts exhaustedlastError, attempts

Catching errors

TypeScript
import {
  BabySea,
  BabySeaError,
  BabySeaTimeoutError,
  BabySeaRetryError,
} from 'babysea';

const client = new BabySea({ apiKey: 'bye_...', region: 'us' });

try {
  await client.generate('google/nano-banana', {
    generation_prompt: 'A cute baby seal',
  });
} catch (err) {
  if (err instanceof BabySeaError) {
    console.log(err.status);     // 402
    console.log(err.code);       // 'BSE1004'
    console.log(err.type);       // 'insufficient_credits'
    console.log(err.message);    // human-readable description
    console.log(err.retryable);  // false
    console.log(err.requestId);  // request trace ID

    // Rate limit info (present on 429 responses)
    if (err.rateLimit) {
      console.log(err.rateLimit.limit);
      console.log(err.rateLimit.remaining);
      console.log(err.rateLimit.reset);
      console.log(err.rateLimit.retryAfter);
    }

    // Provider-level errors (when failover occurred)
    if (err.body.error.provider_errors) {
      for (const pe of err.body.error.provider_errors) {
        console.log(pe.provider); // provider identifier
        console.log(pe.code);
        console.log(pe.message);
      }
    }
  }

  if (err instanceof BabySeaTimeoutError) {
    console.log(err.message); // 'Request timed out after 30000ms'
  }

  if (err instanceof BabySeaRetryError) {
    console.log(err.attempts);              // total attempts made
    console.log(err.lastError.status);      // HTTP status of the last attempt
    console.log(err.lastError.code);        // BSE error code of the last attempt
  }
}