Handle Errors and Rate Limits
Learn how to handle common HTTP errors and rate limiting in Zen Mesh API calls.
What This Recipe Does
This recipe covers:
- Common HTTP status codes and their meanings
- Error response format
- How to handle 401/403/404/409/429/500 errors
- Retry strategies
- Using request IDs for troubleshooting
Error Response Format
All error responses follow this format:
{
"error": "ErrorType",
"message": "Human-readable error message",
"request_id": "req_abc123xyz"
}
| Field | Description |
|---|---|
error | The error type (e.g., ValidationError, Unauthorized) |
message | Detailed explanation of the error |
request_id | Unique identifier for debugging and support |
Common HTTP Status Codes
401 Unauthorized
Authentication failed. The API token is missing, invalid, or expired.
Example Response:
{
"error": "Unauthorized",
"message": "Invalid or expired API token",
"request_id": "req_xyz789"
}
How to Fix:
- Verify your API token in the Zen Mesh dashboard
- Ensure the
ZEN_API_TOKENenvironment variable is set correctly - Test with a simple health check:
curl -sS -H "Authorization: Bearer *** $ZEN_API_BASE/health
403 Forbidden
You don't have permission to perform this action.
Example Response:
{
"error": "ForbiddenError",
"message": "You don't have permission to delete this plane",
"request_id": "req_abc123xyz"
}
How to Fix:
- Verify your token has the required permissions
- Check you're using the correct tenant ID
- Review token scopes/permissions in your dashboard
404 Not Found
The requested resource doesn't exist.
Example Response:
{
"error": "NotFoundError",
"message": "Plane not found: plane_dev_us_east_1",
"request_id": "req_abc123xyz"
}
How to Fix:
- Verify the resource ID is correct
- List resources first to see valid IDs:
curl -sS -H "Authorization: Bearer *** $ZEN_API_BASE/tenants/$ZEN_TENANT_ID/clusters
409 Conflict
The request conflicts with current server state.
Example Response:
{
"error": "ConflictError",
"message": "Plane already exists with this name",
"request_id": "req_abc123xyz"
}
How to Fix:
- Check if the resource already exists
- Use a unique name or ID
- Handle conflicts gracefully in your application
429 Too Many Requests
You've exceeded the rate limit for this endpoint.
Example Response:
{
"error": "RateLimitError",
"message": "Too many requests. Please try again in 60 seconds.",
"request_id": "req_abc123xyz"
}
How to Fix:
- Implement exponential backoff
- Check the
Retry-Afterheader when present:curl -sI "$ZEN_API_BASE/tenants/$ZEN_TENANT_ID/clusters" | grep Retry-After - Reduce request rate
Retry Example (Python):
import time
def fetch_with_retry(url, max_retries=3):
for attempt in range(max_retries):
response = requests.get(url, headers={"Authorization": f"Bearer {token}"})
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
time.sleep(retry_after)
continue
if response.ok:
return response
if attempt == max_retries - 1:
response.raise_for_status()
500 Internal Server Error
An unexpected error occurred on the server.
Example Response:
{
"error": "InternalServerError",
"message": "An unexpected error occurred while processing your request",
"request_id": "req_abc123xyz"
}
How to Fix:
- Retry the request (with backoff)
- Check if
request_idis present - include it when contacting support:I'm getting a 500 error.Request ID: req_abc123xyzEndpoint: POST /tenants/{tenant_id}/clusters - Check status.zen-mesh.io for service status
503 Service Unavailable
The service is temporarily unavailable.
Example Response:
{
"error": "ServiceUnavailableError",
"message": "Service is temporarily unavailable. Please try again later.",
"request_id": "req_abc123xyz"
}
How to Fix:
- Wait and retry
- Check service status page
- Contact support for planned maintenance
Using Request IDs for Troubleshooting
When contacting support, always include the request_id from the error response. This helps support quickly identify the specific request and logs.
Example support message:
I'm getting a 500 Internal Server Error when creating a plane.
Request ID: req_abc123xyz
Endpoint: POST /tenants/{tenant_id}/clusters
Request body: {"name": "plane_dev", ...}
Rate Limiting Strategy
Exponential Backoff
Use progressive delays between retries:
import time
def exponential_backoff_retry(url, max_retries=5, base_delay=1):
for attempt in range(max_retries):
response = requests.get(url, headers={"Authorization": f"Bearer {token}"})
if response.ok:
return response
if response.status_code == 429:
delay = base_delay * (2 ** attempt)
time.sleep(delay)
continue
response.raise_for_status()
Request Batching
Batch similar requests to reduce rate limit hits:
# Instead of:
for plane_id in plane_ids:
requests.get(f"{base_url}/tenants/{tenant_id}/clusters/{plane_id}")
# Do:
plane_list = requests.get(f"{base_url}/tenants/{tenant_id}/clusters").json()
for plane in plane_list['clusters']:
print(plane['id'])
Next Steps
Full API Reference: API Overview
More Information: Authentication | Common Errors