Errors
Every error code, its status and what to do.
Shape
Every error has the same body. message is plain language and safe to show to users. details carries extra fields for some codes. The SDK throws a JustiError with the same fields plus status and retryAfter.
{ "error": { "code": "copy_exists", "message": "...", "details": { "existing": "<mint>" } } }One exception: a swap that fails on chain after submit is not an HTTP error. Submit answers 200 with status: "failed" and an error object, because the request itself worked.
Codes
| code | Status | Meaning | What to do |
|---|---|---|---|
| bad_request | 400 | The request is not valid. | Read message; fix the request. |
| invalid_params | 400 | A parameter is missing or not valid. | details.issues lists each field and what is wrong. |
| invalid_json | 400 | The body is not valid JSON. | Send Content-Type: application/json and a JSON body. |
| unauthorized | 401 | A valid API key is required. | The key is missing, wrong or revoked. Never retried as anonymous. |
| forbidden | 403 | This key cannot do that. | Ask for a partner key if you need it. |
| not_found | 404 | Not found. | Check the mint, id or signature. |
| conflict | 409 | That conflicts with the current state. | Read the current state, then retry. |
| payload_too_large | 413 | The body is too large for this endpoint. | See body limits on the Keys page. Shrink images. |
| rate_limited | 429 | Too many requests. Wait and retry. | Wait Retry-After seconds. Use a key for higher limits. |
| internal | 500 | Something went wrong on our side. | Retry later with backoff. |
| upstream_error | 502 | An upstream service (RPC, Jupiter) did not answer. | Retry with backoff. |
| unavailable | 503 | This is paused or not configured right now. | Check GET /v1/status for the switches. |
| slippage | 400 | The price moved past the slippage limit. | Retry with details.suggestSlippageBps. |
| graduating | 409 | The curve is full and the coin is moving to its DAMM v2 pool. | Retry in a few seconds; trading resumes on DAMM v2. |
| insufficient_funds | 400 | The wallet does not have enough SOL or tokens. | Lower the amount or fund the wallet. |
| expired | 410 | The blockhash expired before it landed. | Build again and sign within about 60 seconds. |
| chain_rejected | 400 | The transaction would fail on chain. | message has the reason from the simulation. |
| copy_exists | 409 | An exact copy of this coin launched in the copy window. | details.existing is the mint. Change any one of ticker, name, image, website, X link. |
| mint_taken | 409 | That mint address is already used or reserved. | Use another custom mint. |
| launch_limit | 429 | This wallet reached its launches per day. | 10 per wallet per day. |
| tx_mismatch | 400 | The signed transaction is not the one that was built. | Sign the returned bytes as they are. Wallets may add instructions to swaps, not launches. |
| signature_invalid | 400 | A required signature is missing or wrong. | Check signers[] in the build response. |
| already_submitted | 409 | This was already submitted. | Poll its status instead. |
| image_fetch_failed | 400 | The image URL could not be fetched. | Use a public https URL under 5 MB, or a data URL. |