Error Response Format
A standard error response follows this schema:code: A strict, non-changing alphanumeric code starting withBSE. 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| Code | Type | HTTP | Retryable | Description |
|---|---|---|---|---|
| BSE1001 | authentication_required | 401 | No | Missing API key |
| BSE1002 | authentication_failed | 401 | No | Invalid API key |
| BSE1003 | insufficient_permissions | 403 | No | API key lacks permission for this resource |
| BSE1004 | insufficient_credits | 402 | No | Not enough credits for this generation |
| BSE1005 | rate_limit_exceeded | 429 | Yes | Per-account rate limit exceeded, check rateLimit.retryAfter |
| BSE1006 | auth_rate_limited | 429 | Yes | Too many requests from this IP (pre-auth) |
| BSE1007 | ip_not_allowed | 403 | No | IP not in API key allowlist |
| BSE1008 | account_not_found | 404 | No | Account associated with this key was not found |
| Code | Type | HTTP | Retryable | Description |
|---|---|---|---|---|
| BSE2001 | invalid_input | 400 | No | Invalid request parameters |
| BSE2002 | file_too_large | 422 | No | Input file exceeds maximum allowed dimensions |
| BSE2003 | file_too_small | 422 | No | Input file below minimum required dimensions |
| BSE2004 | unsupported_file_format | 422 | No | File format not supported (JPEG, PNG, WebP only) |
| BSE2005 | file_load_error | 422 | No | Failed to load or process the provided file |
| BSE2006 | content_policy_violation | 422 | No | Input flagged by content safety filter |
| BSE2007 | file_size_exceeded | 422 | No | File exceeds maximum allowed size in bytes |
| BSE2008 | parameter_out_of_range | 422 | No | A parameter value is outside the allowed range |
| BSE2009 | file_download_error | 422 | No | Failed to download file from URL (must be public) |
| BSE2010 | request_body_too_large | 413 | No | Request body exceeds 100 KB |
| BSE2011 | generation_not_found | 404 | No | Generation ID not found or not owned by this account |
| BSE2012 | generation_not_cancelable | 409 | No | Generation already completed, failed, or canceled |
| BSE2013 | generation_cancel_window_expired | 409 | No | Reserved cancel-window code. Current cancel conflicts typically surface as BSE2012 |
| Code | Type | HTTP | Retryable | Description |
|---|---|---|---|---|
| BSE3001 | model_not_found | 404 | No | Unknown model identifier |
| BSE3002 | model_not_configured | 500 | No | Model exists but is not properly configured |
| BSE3003 | feature_not_supported | 422 | No | Feature or parameter combination not supported by this model |
| Code | Type | HTTP | Retryable | Description |
|---|---|---|---|---|
| BSE4001 | provider_timeout | 504 | Yes | Provider did not respond within the time limit |
| BSE4002 | provider_out_of_memory | 502 | Yes | Model ran out of memory on the provider |
| BSE4003 | all_providers_failed | 502 | Yes | All providers failed, failover exhausted |
| BSE4004 | provider_internal_error | 502 | Yes | Provider encountered an internal error |
| BSE4005 | provider_unavailable | 503 | Yes | Provider temporarily unavailable |
| BSE4006 | prediction_canceled | 409 | No | Prediction was canceled before completion |
| BSE4007 | provider_health_check_failed | 502 | Yes | Model failed its health check on the provider |
| BSE4008 | provider_start_error | 502 | Yes | Provider failed to start the prediction |
| BSE4009 | provider_upload_failed | 502 | Yes | File upload to the provider failed |
| Code | Type | HTTP | Retryable | Description |
|---|---|---|---|---|
| BSE5001 | internal_server_error | 500 | No | Unexpected internal error |
| BSE5002 | database_error | 500 | No | Database read/write failure |
| BSE5003 | storage_error | 500 | No | File storage read/write failure |
Auto-retry behavior
The SDK automatically retries errors whereretryable 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-Afterheader 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
Rate limit headers
Rate limit headers are included on every response:| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests per window |
X-RateLimit-Remaining | Requests remaining in the current window |
X-RateLimit-Reset | Unix timestamp when the window resets |
Retry-After | Seconds 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 yourgeneration_provider_order override.
Solutions:
- The SDK executed retries automatically (verify your
maxRetriesconfiguration). - 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.
- 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-Resetheader) - The SDK respects
Retry-Afterand retries automatically by default - Upgrade your plan for higher rate limits
- Batch requests efficiently to avoid unnecessary calls
Authentication failures
| Code | Cause | Fix |
|---|---|---|
| BSE1001 | Missing API key | Ensure apiKey is set in client config or env |
| BSE1002 | Invalid API key | Verify the key starts with bye_ and is not expired |
| BSE1007 | IP not allowed | Add your IP to the key’s allowlist or remove allowlist |
| BSE1008 | Account not found | The 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
| Class | When thrown | Key properties |
|---|---|---|
BabySeaError | API returns non-2xx | status, code, type, message, retryable, requestId, rateLimit, body |
BabySeaTimeoutError | Request exceeds timeout | message |
BabySeaRetryError | All retry attempts exhausted | lastError, attempts |
Catching errors
TypeScript