API Errors
This guide provides a comprehensive reference for all API errors you may encounter when using LangMart, along with solutions for each.
Authentication Errors (401)
Authentication errors occur when your API key is invalid, missing, or expired.
GATEWAY1_AUTH_001 - Invalid API Key
{
"error": {
"code": "GATEWAY1_AUTH_001",
"message": "Invalid API key",
"type": "authentication_error",
"status": 401
}
}Causes:
- API key is incorrect or misspelled
- API key has been deleted or revoked
- API key belongs to a different environment
Solutions:
- Verify your API key in the dashboard under API Keys
- Ensure you're using the correct format:
Authorization: Bearer YOUR_KEY - Generate a new API key if needed
Provider Authentication Errors
| Error Code | Provider | Solution |
|---|---|---|
PROVIDER_OPENAI_401 |
OpenAI | Update OpenAI API key in Connections |
PROVIDER_ANTHROPIC_401 |
Anthropic | Update Anthropic API key in Connections |
PROVIDER_GOOGLE_401 |
Google AI | Update Google API key in Connections |
PROVIDER_OPENROUTER_401 |
OpenRouter | Update OpenRouter API key in Connections |
To update provider keys:
- Go to Connections in the dashboard
- Find the failing connection
- Click Edit and enter the new API key
- Click Test to verify
Validation Errors (400)
Validation errors occur when your request format or parameters are invalid.
API_VALIDATION_001 - Invalid Request
{
"error": {
"code": "API_VALIDATION_001",
"message": "Invalid request format",
"type": "invalid_request_error",
"status": 400
}
}Common Causes:
- Missing required fields
- Invalid JSON format
- Incorrect parameter types
- Unsupported parameter values
Solutions:
Check required fields:
{
"model": "gpt-4o", // Required
"messages": [ // Required
{
"role": "user", // Required: "user", "assistant", or "system"
"content": "Hello" // Required
}
]
}PROVIDER_ANTHROPIC_400 - Invalid Anthropic Request
Anthropic has specific requirements:
// Correct Anthropic format
{
"model": "claude-3-sonnet-20240229",
"max_tokens": 1024, // Required for Anthropic
"messages": [
{"role": "user", "content": "Hello"}
]
}Common Anthropic issues:
- Missing
max_tokens(required) - System messages must use
systemparameter, not in messages array - Invalid model names
PROVIDER_ANTHROPIC_413 - Request Too Large
{
"error": {
"code": "PROVIDER_ANTHROPIC_413",
"message": "Request exceeds Anthropic size limit",
"status": 413
}
}Solution: Reduce your prompt size or split into multiple requests.
Model Not Found (404)
GATEWAY1_ROUTING_001 - Model Not Found
{
"error": {
"code": "GATEWAY1_ROUTING_001",
"message": "Model 'groq/some-model' not found. It may have been retired, renamed, or never existed.",
"type": "invalid_request_error",
"status": 404
}
}Causes:
- Model name is misspelled
- Model has been retired — withdrawn by its provider, delisted, or the connection serving it was deactivated. A model that used to work and now returns this has almost certainly been retired.
- Model has been deprecated or renamed
- Model is not available in your account
This is the answer for a model that is not there. It used to be reported as a 403
GATEWAY1_AUTH_001 "Access denied to requested model", which sent people looking for a permission
to acquire or an organization to join for a model that had simply been withdrawn. A 403 now means
only what it says — see Forbidden Errors.
Solutions:
- Check available models:
curl -X GET "https://api.langmart.ai/v1/models" \
-H "Authorization: Bearer YOUR_API_KEY"- Use the correct model identifier format:
provider/model-name
PROVIDER_OPENROUTER_POLICY - Data Policy Restriction
{
"error": {
"code": "PROVIDER_OPENROUTER_POLICY",
"message": "OpenRouter data policy restriction - free models require data sharing",
"status": 404
}
}Solution:
- Go to https://openrouter.ai/settings/privacy
- Enable data sharing for free models
- Or use a paid model instead
Rate Limit Errors (429)
Provider Rate Limits
{
"error": {
"code": "PROVIDER_OPENAI_429",
"message": "Rate limit exceeded",
"type": "rate_limit_error",
"status": 429
},
"retry_after": 60
}| Error Code | Provider | Action |
|---|---|---|
PROVIDER_OPENAI_429 |
OpenAI | Wait and retry with backoff |
PROVIDER_ANTHROPIC_429 |
Anthropic | Wait and retry with backoff |
PROVIDER_GOOGLE_429 |
Google AI | Check quota at console |
PROVIDER_GOOGLE_QUOTA |
Google AI | Upgrade quota |
PROVIDER_OPENROUTER_429 |
OpenRouter | Wait and retry |
Response Headers:
Retry-After: 60
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 2025-01-15T14:30:00ZSolutions:
- Wait for
Retry-Afterseconds before retrying - Implement exponential backoff
- Spread requests across multiple providers
- Upgrade to higher tier with provider
Billing Errors (402)
GATEWAY1_BILLING_001 - Insufficient Credits
{
"error": {
"code": "GATEWAY1_BILLING_001",
"message": "Insufficient credits. Your balance ($0.05) is below the minimum required ($0.10).",
"type": "billing_error",
"status": 402
}
}Solution: Add credits to your account. See Billing Issues.
context_data carries the threshold under both minimum_threshold and minimum_required — the
same value under two names, because the gateway has always sent the first and the web app reads the
second.
When the model is billed to your organization (org_billing_mode = 'org_pays'), the balance quoted
is the organization's, not yours, and context_data.payer reads organization. Adding credits
to your personal account will not clear it — an organization admin has to fund the organization.
Where the credit check applies
The check runs on every inference entry point, before the request reaches a provider — so a 402 means nothing was sent upstream and nothing was spent:
| Endpoint | Format |
|---|---|
POST /v1/chat/completions |
OpenAI chat |
POST /v1/completions |
OpenAI text completions |
POST /v1/embeddings |
OpenAI embeddings |
POST /v1/messages (also POST /api/messages) |
Anthropic messages |
POST /v1/images/generations |
OpenAI image generation |
POST /native/{provider}/* |
provider-native passthrough |
/v1/completions, /v1/embeddings, /v1/messages and /v1/images/generations gained the check on
2026-08-29; before that only /v1/chat/completions and /native/* carried it, and the other four
were reconciled only after the fact by settlement. If you have code that relied on a request going
through while the paying account was empty, it will now be refused up front.
The same rule applies whichever gateway is serving as the active inference server. Gateway Type 0
uses the GATEWAY0_BILLING_001 / GATEWAY0_BILLING_002 codes for the identical conditions — the
message, the status and context_data are the same.
A model billed to an organization is checked against that organization's balance on every one of these endpoints, not just on chat completions.
Service Errors (503)
GATEWAY1_BILLING_002 - Invalid Model Price
{
"error": {
"code": "GATEWAY1_BILLING_002",
"message": "Model openrouter/openrouter/auto is mispriced in the catalogue and cannot be billed. This is a platform fault, not a problem with your account — please contact support.",
"type": "invalid_model_price",
"status": 503
}
}Cause: the model's catalogue price is negative, which makes billing impossible to compute correctly. The request is refused before it reaches the provider, so you are not charged and no tokens are spent.
This is not a credit problem. Adding funds will not help — the fault is in our catalogue.
Solutions:
- Use a different model; other models are unaffected.
- Report the model id to support so the price can be corrected.
- Retry later: once the price is fixed the same request succeeds unchanged.
Applies on the same endpoints as the 402 above — see Where the credit check
applies — and on Gateway Type 0 as GATEWAY0_BILLING_002.
Connection Test Errors
POST /api/connections/:id/test reports what happened to the test, not to your request. Three
answers changed shape; callers should branch on code, never on the HTTP status alone (403 is now
used by three different codes on this route).
| HTTP | code |
Meaning | Repair |
|---|---|---|---|
| 400 | auth_failed |
the provider rejected the key | replace the key (Update API Key) |
| 403 | auth_scope_denied |
the key is valid but may not list models (e.g. an OpenAI key without api.model.read) |
widen the key's scopes — replacing it will not help. Previously reported as 400 auth_failed. |
| 403 | system_connection_protected |
a platform-managed connection cannot be tested | nothing; this is expected |
| 502 | internal_auth_failed |
the platform's own internal discovery call was not authorised | a platform fault. Nothing has been learned about your key — it is not counted as a failure and no model is disabled |
internal_auth_failed exists because the health checker used to report exactly this condition as
auth_failed: for months every automated check failed at our own front door and was recorded as
"API key may be invalid" against connections whose credentials had never been contacted.
Forbidden Errors (403)
GATEWAY1_AUTH_002 - Access Denied
{
"error": {
"code": "GATEWAY1_AUTH_002",
"message": "Access denied",
"type": "forbidden",
"status": 403
}
}Causes:
- Insufficient permissions
- Resource belongs to another organization
- Feature not available on your plan
For a model, this now means exactly one thing: the model exists and is visible, and your account
may not use it — someone else's individual model, or an organization model you are not a member of.
A model that does not exist, or has been retired, answers 404 GATEWAY1_ROUTING_001 instead.
Solutions:
- Check your organization membership
- Verify you have access to the requested resource
- Contact your organization admin
MASTER_ADMIN_AUTH_001 - Platform administrators only
Some /api/admin reads are not about your organization — they report on the whole platform, or on
the platform organization itself. Being an admin of your own organization is not enough for those,
and since 2026-08-29 they answer 403 MASTER_ADMIN_AUTH_001 instead of serving another tenant's data:
| Endpoint | Why it is platform-only | What to use instead |
|---|---|---|
GET /api/admin/org-billing/* |
every query reports on the platform organization, never on the caller's | GET /api/organizations/:org_id/billing and /usage for your own org |
GET /api/admin/quotas/summary |
get_quota_usage_summary() takes no organization argument — the totals span every organization |
GET /api/admin/quotas/users and /api/admin/quotas/org-breakdown, both filtered to your org |
GET /api/admin/metrics/overview |
aggregates model_usage_metrics across all organizations, including a platform-wide user count |
GET /api/admin/metrics/my/* for yourself; /api/admin/metrics/users/:user_id/* for a user you may view |
GET /api/admin/quotas/templates stays open to organization admins, but ?organization_id= is no
longer taken on trust: naming an organization other than your own answers 403 rather than returning
its templates. Omit the parameter to get your own. Platform admins may still name any organization.
Server Errors (500+)
SYSTEM_DB_001 - Database Error
{
"error": {
"code": "SYSTEM_DB_001",
"message": "Database operation failed",
"type": "api_error",
"status": 500
}
}Solution: This is usually temporary. Wait and retry. If persistent, contact support.
Gateway Errors (503/504)
GATEWAY3_CONN_001 - Gateway Unavailable
{
"error": {
"code": "GATEWAY3_CONN_001",
"message": "Gateway temporarily unavailable",
"status": 503
}
}GATEWAY_TIMEOUT_001 - Gateway Timeout
{
"error": {
"code": "GATEWAY_TIMEOUT_001",
"message": "Gateway did not respond within 60s",
"type": "gateway_timeout",
"status": 504
},
"retry_after": 5,
"gateway_id": "gw-123",
"gateway_type": "type3"
}Solutions:
- Retry with exponential backoff
- Check system status for outages
- Reduce request size for timeout errors
- Use streaming for large responses
Routing Errors (503)
ROUTE_SELECTION_FAILED - All Routes Failed
{
"error": {
"code": "ROUTE_SELECTION_FAILED",
"message": "Unable to route to any available model",
"status": 503
}
}Causes:
- All configured connections are failing
- No healthy targets available
- Circuit breakers are open
Solutions:
- Check connection status in dashboard
- Test individual connections
- Verify provider API keys
- Wait for circuit breakers to reset
Other Routing Errors
| Error Code | Description | Solution |
|---|---|---|
ROUTE_NO_MODELS |
No models available | Check model availability |
FALLBACK_CHAIN_EXHAUSTED |
All fallbacks failed | Check all connections |
CIRCUIT_BREAKER_OPEN |
Circuit breaker tripped | Wait for reset |
LB_NO_TARGETS |
No load balancer targets | Configure connections |
LB_NO_HEALTHY_TARGETS |
All targets unhealthy | Check connection health |
RETRY_LIMIT_EXCEEDED |
Max retries reached | Check underlying errors |
Provider-Specific Errors
Anthropic
| Error Code | Description | Solution |
|---|---|---|
PROVIDER_ANTHROPIC_529 |
Service overloaded | Wait and retry |
PROVIDER_ANTHROPIC_400 |
Invalid request | Check request format |
PROVIDER_ANTHROPIC_413 |
Request too large | Reduce prompt size |
Google AI
| Error Code | Description | Solution |
|---|---|---|
PROVIDER_GOOGLE_QUOTA |
Quota exceeded | Check console quotas |
PROVIDER_GOOGLE_429 |
Rate limited | Implement backoff |
Error Code Reference Table
| Status | Error Code | Category | Description |
|---|---|---|---|
| 400 | API_VALIDATION_001 | Client | Invalid request |
| 400 | PROVIDER_ANTHROPIC_400 | Client | Invalid Anthropic request |
| 401 | GATEWAY1_AUTH_001 | Auth | Invalid API key |
| 401 | PROVIDER_OPENAI_401 | Auth | OpenAI auth failed |
| 401 | PROVIDER_ANTHROPIC_401 | Auth | Anthropic auth failed |
| 401 | PROVIDER_GOOGLE_401 | Auth | Google auth failed |
| 401 | PROVIDER_OPENROUTER_401 | Auth | OpenRouter auth failed |
| 402 | GATEWAY1_BILLING_001 | Billing | Insufficient credits (yours or your organization's) — every inference endpoint |
| 402 | GATEWAY0_BILLING_001 | Billing | The same, from Gateway Type 0 |
| 403 | GATEWAY1_AUTH_002 | Auth | Access denied |
| 403 | GATEWAY1_AUTH_001 | Routing | Model exists and is visible, but your account may not use it |
| 404 | GATEWAY1_ROUTING_001 | Routing | Resource not found (incl. a retired or unknown model) |
| 404 | PROVIDER_OPENROUTER_POLICY | Provider | Data policy restriction |
| 413 | PROVIDER_ANTHROPIC_413 | Client | Request too large |
| 429 | PROVIDER_OPENAI_429 | Rate Limit | OpenAI rate limited |
| 429 | PROVIDER_ANTHROPIC_429 | Rate Limit | Anthropic rate limited |
| 429 | PROVIDER_GOOGLE_429 | Rate Limit | Google rate limited |
| 429 | PROVIDER_GOOGLE_QUOTA | Rate Limit | Google quota exceeded |
| 429 | PROVIDER_OPENROUTER_429 | Rate Limit | OpenRouter rate limited |
| 500 | SYSTEM_DB_001 | Server | Database error |
| 503 | GATEWAY1_BILLING_002 | Billing | Model price is invalid — platform fault, not your balance |
| 503 | GATEWAY0_BILLING_002 | Billing | The same, from Gateway Type 0 |
| 500 | SYSTEM_UNKNOWN_001 | Server | Unknown error |
| 503 | GATEWAY3_CONN_001 | Server | Gateway unavailable |
| 503 | ROUTE_SELECTION_FAILED | Server | Routing failed |
| 503 | ROUTE_NO_MODELS | Server | No models available |
| 503 | FALLBACK_CHAIN_EXHAUSTED | Server | All fallbacks failed |
| 503 | CIRCUIT_BREAKER_OPEN | Server | Circuit breaker open |
| 503 | LB_NO_TARGETS | Server | No LB targets |
| 503 | LB_NO_HEALTHY_TARGETS | Server | No healthy targets |
| 504 | GATEWAY_TIMEOUT_001 | Server | Gateway timeout |
| 504 | ROUTE_SELECTION_TIMEOUT | Server | Selection timeout |
| 529 | PROVIDER_ANTHROPIC_529 | Provider | Anthropic overloaded |
Best Practices for Error Handling
Implement Comprehensive Error Handling
import requests
def make_langmart_request(data):
try:
response = requests.post(
"https://api.langmart.ai/v1/chat/completions",
headers={"Authorization": "Bearer YOUR_KEY"},
json=data,
timeout=120
)
if response.status_code == 200:
return response.json()
error = response.json().get('error', {})
error_code = error.get('code')
# Handle specific errors
if response.status_code == 401:
raise AuthenticationError(f"Auth failed: {error.get('message')}")
if response.status_code == 402:
raise BillingError("Insufficient credits")
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
raise RateLimitError(f"Rate limited, retry after {retry_after}s")
if response.status_code >= 500:
raise ServerError(f"Server error: {error_code}")
raise APIError(f"Request failed: {error.get('message')}")
except requests.Timeout:
raise TimeoutError("Request timed out")
except requests.ConnectionError:
raise ConnectionError("Failed to connect")Log Errors for Debugging
Always include the request ID in your logs:
response = requests.post(...)
request_id = response.headers.get('x-request-id')
if not response.ok:
logger.error(f"Request {request_id} failed: {response.json()}")Related Documentation
- Connection Issues - Network troubleshooting
- Billing Issues - Payment problems
- Error Tracking - Monitor errors