Errors
CoAI Sandbox answers errors like E2B's API, as {"code": <HTTP status>, "error_code": "<code>", "message": "<text>"}. The
SDKs raise an exception with the status (status_code in Python, statusCode in JavaScript) and the message.
Creating a sandbox
| Code | Status | Message | What to do | SDK retries |
|---|---|---|---|---|
insufficient_balance |
402 | Insufficient balance. Add funds: | Add funds, or pay an unpaid settlement invoice | no |
account_not_verified |
403 | This account is not enabled for CoAI Sandbox yet | Verify your account with a saved card | no |
account_frozen |
403 | This account is frozen | Contact support | no |
sandbox_concurrency_limit |
429 | You have reached the maximum number of concurrent sandboxes (N) | Kill sandboxes you no longer need | no |
daily_create_limit |
429 | You have reached the maximum number of sandboxes created today (N) | Wait for the next UTC day | no |
spend_cap_reached |
429 | You have reached your spend cap; raise it or wait for the next period | Raise the cap in the console | no |
create_rate_limited |
429 | You are creating sandboxes too fast, try again shortly | Nothing: the SDK waits Retry-After |
yes |
rate_limited |
429 | Too many requests, try again shortly | Fewer requests per API key | yes |
timeout_too_long |
400 | Timeout cannot be greater than 30 minutes | A shorter timeout (your level's limit) | no |
unsupported_feature |
400 | autoPause is not supported by CoAI Sandbox yet | Leave the option out (compatibility page) | no |
billing_unavailable |
503 | Billing is temporarily unavailable, try again shortly | Nothing: running sandboxes are not affected; try again later if it persists | yes |
maintenance |
503 | CoAI Sandbox is under maintenance, try again later | Wait | yes |
sandbox_capacity_unavailable |
503 | No sandbox capacity is available now, try again | Nothing: the SDK retries; retry later if it persists | yes |
Retries. For a 429 with Retry-After and for every 503, the SDKs retry up to 3 times and wait Retry-After before each retry: 60 s for billing_unavailable, 30 s for maintenance, 2 s for sandbox_capacity_unavailable (30 s when the template has no capacity), 1 s for rate_limited, up to 60 s for create_rate_limited. A create refused with billing_unavailable therefore raises only after about 3 minutes, one refused with maintenance after about 1.5 minutes.
A wrong, revoked or missing API key is 401; the Python SDK raises AuthenticationException, the JavaScript SDK
AuthenticationError. Check E2B_API_KEY and E2B_DOMAIN.
Handling them
The SDKs map the statuses to their exception classes: 429 is RateLimitException / RateLimitError, 503 is
ServiceBusyException / ServiceBusyError (raised after the SDK's own retries; in Python it is not a
SandboxException), the others are SandboxException / SandboxError with the status code.
Python:
# How CoAI Sandbox's refusals reach your code, with the official E2B SDK for Python.
# Usage: python errors.py [timeout in seconds]
import sys
from e2b import RateLimitException, Sandbox, SandboxException, ServiceBusyException
def create_sandbox(timeout=300):
"""A new sandbox, or None after printing why CoAI Sandbox refused it."""
try:
return Sandbox.create(timeout=timeout)
except RateLimitException as e: # 429: running sandboxes, sandboxes today or a spending cap
print("limit reached:", e)
except ServiceBusyException as e: # 503 after the SDK's retries: billing unavailable or maintenance
print("try again later:", e)
except SandboxException as e:
if e.status_code == 402: # insufficient balance: the message links to Add Funds
print("add funds first:", e)
elif e.status_code == 403: # not verified yet, or frozen
print("account not ready:", e)
elif e.status_code == 400: # for example a timeout longer than your level allows
print("request refused:", e)
else:
raise
return None
if __name__ == "__main__":
sbx = create_sandbox(int(sys.argv[1]) if len(sys.argv) > 1 else 300)
if sbx is not None:
print("created", sbx.sandbox_id)
sbx.kill()
JavaScript:
// How CoAI Sandbox's refusals reach your code, with the official E2B SDK for JavaScript.
// Usage: node errors.mjs [timeout in seconds]
import { RateLimitError, Sandbox, SandboxError, ServiceBusyError } from 'e2b'
// A new sandbox, or null after printing why CoAI Sandbox refused it.
async function createSandbox(timeoutMs = 300_000) {
try {
return await Sandbox.create({ timeoutMs })
} catch (e) {
if (e instanceof RateLimitError) {
console.log('limit reached:', e.message) // 429: running sandboxes, sandboxes today or a spending cap
} else if (e instanceof ServiceBusyError) {
console.log('try again later:', e.message) // 503 after the SDK's retries: billing unavailable or maintenance
} else if (e instanceof SandboxError && e.statusCode === 402) {
console.log('add funds first:', e.message) // insufficient balance: the message links to Add Funds
} else if (e instanceof SandboxError && e.statusCode === 403) {
console.log('account not ready:', e.message) // not verified yet, or frozen
} else if (e instanceof SandboxError && e.statusCode === 400) {
console.log('request refused:', e.message) // for example a timeout longer than your level allows
} else {
throw e
}
return null
}
}
const sbx = await createSandbox(1000 * Number(process.argv[2] ?? 300))
if (sbx !== null) {
console.log('created', sbx.sandboxId)
await sbx.kill()
}
A running sandbox stopped
A sandbox ends when its timeout passes, at your level's longest running time, when your balance or a spending cap is used up
(after a grace period of about a minute), when your account is frozen, or when it is stopped under the Acceptable Use Policy.
After that, calls to it answer 404 sandbox_not_found (NotFoundException / NotFoundError). The console lists your
sandboxes with the reason each one ended, and you get an e-mail notice when sandboxes were stopped for the balance or a cap.