Error Handling
The Daytona API uses standard HTTP status codes to indicate success or failure of requests. All error responses include a JSON body with detailed error information.
Error responses follow a consistent structure:
{
"statusCode" : 400 ,
"message" : "Bad Request" ,
"error" : "Validation failed: snapshot is required"
}
HTTP status code (4xx for client errors, 5xx for server errors)
Human-readable error summary
Detailed error description with context
HTTP Status Codes
Success Codes (2xx)
Request succeeded. Response body contains requested data.
Resource created successfully. Response body contains the new resource.
Request succeeded. No response body (common for DELETE operations).
Client Error Codes (4xx)
Invalid request format, missing required fields, or validation errors.
Missing, invalid, or expired authentication credentials.
Authenticated but lacks permission to access the resource.
Requested resource does not exist.
Request conflicts with current state (e.g., duplicate resource).
Server Error Codes (5xx)
500 Internal Server Error
Unexpected server error. Contact support if persistent.
Upstream service unavailable. Retry with exponential backoff.
Service temporarily unavailable (maintenance or overload).
Common Error Scenarios
Authentication Errors
Missing API Key
{
"statusCode" : 401 ,
"message" : "Unauthorized" ,
"error" : "No authorization header provided"
}
Solution: Include the Authorization header:
-H "Authorization: Bearer YOUR_API_KEY"
Invalid API Key
{
"statusCode" : 401 ,
"message" : "Unauthorized" ,
"error" : "Invalid or expired API key"
}
Solutions:
Verify your API key is correct
Check if the key has expired
Create a new API key if needed
Insufficient Permissions
{
"statusCode" : 403 ,
"message" : "Forbidden" ,
"error" : "API key lacks required permission: write:sandboxes"
}
Solution: Create an API key with appropriate permissions:
daytona api-key create "My Key" --permissions write:sandboxes
Validation Errors
Missing Required Field
{
"statusCode" : 400 ,
"message" : "Bad Request" ,
"error" : "Validation failed: snapshot is required"
}
Solution: Include all required fields in the request:
{
"snapshot" : "ubuntu:22.04" ,
"alias" : "my-sandbox"
}
Invalid Field Value
{
"statusCode" : 400 ,
"message" : "Bad Request" ,
"error" : "Invalid value for cpu: must be between 1 and 32"
}
Solution: Provide valid values within acceptable ranges.
{
"statusCode" : 400 ,
"message" : "Bad Request" ,
"error" : "Invalid JSON: Unexpected token at position 45"
}
Solution: Ensure request body is valid JSON:
# Use jq or similar to validate JSON
echo '{"snapshot": "ubuntu:22.04"}' | jq .
Resource Errors
Resource Not Found
{
"statusCode" : 404 ,
"message" : "Not Found" ,
"error" : "Sandbox not found: sandbox_abc123"
}
Solutions:
Verify the resource ID is correct
Check if the resource was deleted
Ensure you have access to the resource
Resource Conflict
{
"statusCode" : 409 ,
"message" : "Conflict" ,
"error" : "A sandbox with alias 'my-sandbox' already exists"
}
Solution: Use a unique alias or update the existing resource.
Rate Limit Errors
{
"statusCode" : 429 ,
"message" : "Too Many Requests" ,
"error" : "Rate limit exceeded. Please retry after 45 seconds." ,
"retryAfter" : 45
}
Solutions:
Wait for the time specified in retryAfter
Implement exponential backoff
See Rate Limits for best practices
Organization Context Errors
Missing Organization ID
{
"statusCode" : 400 ,
"message" : "Bad Request" ,
"error" : "X-Daytona-Organization-ID header required for JWT tokens"
}
Solution: Include organization header for JWT authentication:
-H "X-Daytona-Organization-ID: org_abc123"
Quota Errors
Organization Quota Exceeded
{
"statusCode" : 403 ,
"message" : "Forbidden" ,
"error" : "Organization quota exceeded: maximum 10 active sandboxes allowed"
}
Solutions:
Delete unused sandboxes
Stop sandboxes not in use
Upgrade your organization plan
Contact support for quota increase
Region Quota Exceeded
{
"statusCode" : 403 ,
"message" : "Forbidden" ,
"error" : "Region quota exceeded for us-east: CPU limit reached"
}
Solutions:
Use a different region
Reduce resource allocation
Contact support for regional quota adjustment
Error Handling Best Practices
Implement Retry Logic
import requests
import time
def make_request_with_retry ( url , headers , max_retries = 3 ):
for attempt in range (max_retries):
try :
response = requests.get(url, headers = headers)
# Success
if response.status_code < 400 :
return response.json()
# Client error (don't retry)
if 400 <= response.status_code < 500 :
if response.status_code == 429 : # Rate limit
retry_after = int (response.headers.get( 'Retry-After' , 60 ))
time.sleep(retry_after)
continue
else :
raise Exception ( f "Client error: { response.json() } " )
# Server error (retry with backoff)
if response.status_code >= 500 :
if attempt < max_retries - 1 :
wait_time = 2 ** attempt
time.sleep(wait_time)
continue
else :
raise Exception ( f "Server error: { response.json() } " )
except requests.exceptions.RequestException as e:
if attempt < max_retries - 1 :
time.sleep( 2 ** attempt)
continue
else :
raise e
raise Exception ( "Max retries exceeded" )
Validate Before Sending
function validateSandboxRequest ( data : any ) : string [] {
const errors : string [] = [];
if ( ! data . snapshot ) {
errors . push ( 'snapshot is required' );
}
if ( data . cpu && ( data . cpu < 1 || data . cpu > 32 )) {
errors . push ( 'cpu must be between 1 and 32' );
}
if ( data . memoryGiB && ( data . memoryGiB < 1 || data . memoryGiB > 128 )) {
errors . push ( 'memoryGiB must be between 1 and 128' );
}
return errors ;
}
// Use before making request
const errors = validateSandboxRequest ( requestData );
if ( errors . length > 0 ) {
console . error ( 'Validation errors:' , errors );
return ;
}
Log Error Details
import (
" fmt "
" log "
)
func handleAPIError ( err error , response * http . Response ) {
if response . StatusCode >= 400 {
var errorBody map [ string ] interface {}
json . NewDecoder ( response . Body ). Decode ( & errorBody )
log . Printf ( "API Error [ %d ]: %v " ,
response . StatusCode ,
errorBody [ "error" ])
// Log additional context
log . Printf ( "Request ID: %s " ,
response . Header . Get ( "X-Request-ID" ))
log . Printf ( "Timestamp: %s " ,
time . Now (). Format ( time . RFC3339 ))
}
}
Graceful Degradation
def get_sandboxes_with_fallback ( api_client ):
try :
# Try to get sandboxes
return api_client.sandboxes.list()
except RateLimitError:
# Rate limited, return cached data
return get_cached_sandboxes()
except APIError as e:
if e.status_code >= 500 :
# Server error, use fallback
logger.error( f "API unavailable: { e } " )
return get_cached_sandboxes()
else :
# Client error, propagate
raise
Debugging Tips
Use verbose mode to see full request/response details: curl -v -X GET https://api.daytona.io/sandbox \
-H "Authorization: Bearer YOUR_API_KEY"
Every response includes a request ID for troubleshooting: X-Request-ID: req_abc123xyz
Include this when contacting support.
Validate with OpenAPI Spec
Use tools like Swagger UI or Postman to validate requests against the OpenAPI specification.
Before implementing in code, test with curl to isolate issues: curl -X POST https://api.daytona.io/sandbox \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"snapshot": "ubuntu:22.04"}'
Getting Help
If you encounter persistent errors:
Check status page - Verify there are no ongoing incidents
Review documentation - Ensure you’re using the API correctly
Search community - Check if others have encountered similar issues
Contact support - Include request ID, error message, and reproduction steps
Include the X-Request-ID header value when reporting errors to support for faster resolution.
Next Steps
Authentication Fix authentication errors
Rate Limits Handle rate limit errors
SDKs Use SDKs with built-in error handling
Support Get help from the community