Error codes
HTTP status + a JSON error envelope. The envelope matches OpenAI's shape so existing client error handling keeps working.
Envelope
{
"error": {
"type": "insufficient_balance",
"message": "Top up at portal.greenjoules.cloud.",
"code": 402,
"request_id": "req_018a3c..."
}
}
Status reference
| Status | type | What it means | What to do |
|---|---|---|---|
| 400 | bad_request | Malformed JSON, missing required field, invalid model name. | Fix the request payload; check error.message. |
| 401 | invalid_api_key | Missing, malformed, or revoked token. | Mint a new token in the portal. |
| 403 | insufficient_scope | Token doesn't have the scope needed for this endpoint (e.g. an inference token trying to deploy). | Use a token with the right scope, or upgrade the existing one in the portal. |
| 404 | not_found | Endpoint, workload, receipt, or model doesn't exist. | Check the path / id. |
| 409 | conflict | Workload name collision; receipt already verified; etc. | Pick a unique name; or treat as success-already-done. |
| 413 | payload_too_large | Request body exceeds 50 MB (10 MB for the Inference endpoints). | For chat: chunk; for Object Store: use multipart upload. |
| 422 | unprocessable_entity | Valid JSON, semantically invalid (e.g. messages empty, malformed tools schema). | Check the schema; the message names the field. |
| 429 | energy_budget_exceeded | The workload hit its energy_budget. Or you exceeded the per-account anti-abuse cap (rare). | Raise the workload budget or wait for the window to roll over. |
| 402 | insufficient_balance | Account balance hit zero or went negative. | Top up at the portal. Workloads automatically resume when balance is positive again. |
| 500 | internal_error | We broke something. Always a bug on our side. | Retry with backoff; if persistent, write to [email protected] with request_id. |
| 502 | upstream_error | An underlying provider/model timed out or rejected the request. | Retry; use "auto" instead of pinning if a specific model is flaky. |
| 503 | service_unavailable | A region/node is degraded. | Retry; the mesh fails over within ~10s. Check status. |
| 504 | timeout | Request took longer than the per-endpoint timeout (30s for inference; 5m for batch). | Reduce max_tokens; chunk the request; or use a streaming endpoint. |
CLI exit codes
For the jc CLI specifically:
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Generic error |
| 2 | Bad input / argument |
| 3 | Auth failure (401) |
| 4 | Resource not found (404) |
| 10 | Insufficient balance (402) |
| 20 | Energy budget exceeded (429) |
Retry policy
Idempotent operations (GET, PUT to Object Store, DELETE) are safe to retry without coordination. Non-idempotent operations (POST that creates a new resource, chat completions) should use the Idempotency-Key request header — we deduplicate retries with the same key for 24 hours.
Rate-limit headers
Even when we don't throttle (we don't have per-minute caps), every response carries informational headers so you can self-pace:
X-Joule-Budget-Used: 1240
X-Joule-Budget-Cap: 10000
X-Joule-Budget-Reset: 1782273434
Where to look first when things break
- The
error.messagefield. We try to make it specific. - The
error.request_id. If you ask us for help, include it. - status.greenjoules.cloud — check for ongoing incidents.
- The signed receipt for any prior successful call — tells you exactly what silicon you were on, useful for "it was working an hour ago" debugging.
- If still stuck:
[email protected]with the request ID and a minimal repro.