Try the interactive chat
Errors
Error response formats, every error code, retry rules and recovery steps.
Errors use OpenAI's error format. OpenAI SDKs convert them into their own error classes.
This format applies to the documented JSON endpoints. Unknown paths or incorrect HTTP methods return PocketBase's 404 format with status, message and data, without an error field.
{
"error": {
"message": "Bu tarayıcı anahtarı bu sitede kullanılamaz. Siteyi anahtarın izinli siteleri arasına ekleyin.",
"type": "permission_error",
"param": null,
"code": "origin_not_allowed"
}
}messageis a simple, visitor-facing Turkish explanation. The example above preserves the actual server language.codeis stable and English. Always branch oncode, notmessage.paramidentifies the invalid field, such asmodel,messages,inputorafter, or isnullwhen no field applies.
POST /chat is the exception: its body is plain Turkish text containing the message. Vercel AI SDK exposes it as useChat's error.message. The code appears in X-Sone-Error-Code; this header is available to server requests, but is not exposed to browser code.
Codes
Do not repeat the same request when x-should-retry is false. Retry-After is the wait specified by that header.
| Status | code | x-should-retry | Retry-After | Meaning and recovery |
|---|---|---|---|---|
400 | invalid_body | none | none | Body is empty or unreadable. Send a JSON body. |
400 | invalid_json | none | none | Invalid JSON or an incorrect field type. See message for details. |
400 | missing_user_message | none | none | The final message must be a user message containing text. |
400 | invalid_role | none | none | Unknown message role, or a Responses message item without a role. |
400 | invalid_content | none | none | Message content is not a string or an array of parts. |
400 | unsupported_content | none | none | A new message contains an image, audio or file. Send text only. |
400 | message_too_long | none | none | A new message exceeds 4,000 characters. Shorten it. |
400 | too_many_new_messages | none | none | More than 12 new visitor messages in one request. Include the assistant reply in history before continuing, or start a new conversation. |
400 | tools_not_supported | none | none | Remove tools, functions or function-call items. The assistant uses the business tools configured in Sonecentral. |
400 | unsupported_parameter | none | none | n is not 1, response_format or text.format is not text, or background is true. param identifies the field. |
400 | missing_input | none | none | Responses request has no input. |
400 | invalid_input | none | none | Responses input is not text or an array of items. |
400 | unsupported_item | none | none | Unknown Responses input item type. |
400 | conflicting_parameters | none | none | previous_response_id and conversation were supplied together. Use one. |
400 | instructions_too_long | none | none | Responses instructions exceeds 2,000 characters or 4 KB JSON. |
400 | invalid_metadata | none | none | Responses metadata exceeds 16 keys, 64 characters per key, 512 characters per string value, or 4 KB JSON. Values must be strings. |
400 | safety_identifier_too_long | none | none | Responses safety_identifier exceeds 64 characters. |
400 | user_too_long | none | none | Responses user exceeds 64 characters. |
400 | previous_response_id_too_long | none | none | Trimmed previous_response_id is longer than a response ID. Send the original response id. |
400 | item_id_too_long | none | none | An item_reference ID exceeds 64 characters. |
400 | conversation_model_mismatch | false | none | The conversation belongs to another assistant. Use the same model or start a new conversation. |
400 | conversation_full | false | none | The conversation has reached 200 visitor messages. Start a new one. |
400 | invalid_cursor | none | none | after is not a message ID in this conversation. Clear the cursor and read from the start. |
400 | not_cancellable | none | none | Responses complete within the request; there is no background task to cancel. |
401 | missing_api_key | none | none | No key supplied. |
401 | invalid_api_key | none | none | Unknown or malformed key, or prefix does not match its type. |
401 | revoked_api_key | none | none | The key was revoked. Create a new one. |
402 | plan_required | false | none | The workspace plan does not permit assistant replies. The assistant did not reply. |
403 | origin_not_allowed | none | none | Publishable key used without Origin or outside its allowed origins. Add the site to the key. |
403 | secret_key_in_browser | none | none | A server key was used from a browser. Use a publishable key. |
404 | model_not_found | none | none | No published assistant with this ID is available to the key. GET /models lists available assistants. |
404 | conversation_not_found | none | none | Not an API conversation in this workspace, or its assistant is unavailable to the key. Clear the saved ID and start a new conversation. |
404 | previous_response_not_found | none | none | The referenced response is missing, deleted, was created with store: false, or belongs to an assistant unavailable to the key. |
404 | response_not_found | none | none | Stored response is missing, deleted, older than 30 days or unavailable to the key. On DELETE, also returned when another key stored it. |
404 | file_not_found | none | none | Invalid or expired signed URL. Read conversation messages again to obtain a fresh URL. |
409 | conversation_busy | none | 2 | The previous turn is still running. This message was not stored. Wait and retry with the same Idempotency-Key. |
413 | request_too_large | none | none | Body exceeds 1 MB. Send the conversation ID instead of the full history. |
422 | idempotency_key_reused | false | none | The same Idempotency-Key was used with different text. Use a new key for each new message. |
429 | rate_limit_exceeded | none | Window-dependent | Request or read limit exceeded. Wait for Retry-After. |
429 | ai_turn_ceiling | false | 300 | The workspace hourly/daily API reply limit, or its publishable-key share, was reached. The assistant did not reply. |
429 | assistant_quota_exhausted | false | none | Sonecentral AI capacity is temporarily unavailable. Your workspace has not exhausted a plan allowance; API replies do not consume it. The assistant did not reply. |
429 | file_download_limit | none | Window-dependent | This file ID was downloaded 10 times in the last hour. Wait for Retry-After. |
429 | file_egress_limit | none | Until midnight UTC | Workspace daily file download limit reached. |
503 | assistant_paused | If delivered to team false | 60 | Automatic replies are disabled. The assistant did not reply. |
503 | assistant_unavailable | none | 30 | The assistant is temporarily unavailable. Wait and retry with the same Idempotency-Key. |
503 | conversation_not_created | none | none | The conversation could not be created. Retry later. |
503 | message_not_stored | none | none | The message could not be stored. Retry with the same Idempotency-Key. |
503 | messages_unavailable | none | none | Conversation messages could not be read. Retry on the next poll. |
503 | file_unavailable | none | none | The file is temporarily unavailable. Retry later. |
503 | response_not_deleted | none | none | The stored response could not be deleted. Retry later. |
Retry-After is measured in seconds and rounded up.
Two other cases may use a different body: more than 120 file-download requests per minute from one address returns a non-OpenAI 429; unexpected server errors may also have another format. Retry unexpected 5xx responses with the same Idempotency-Key.
Where messages go when the assistant cannot reply
plan_required, assistant_quota_exhausted, ai_turn_ceiling and assistant_paused mean the assistant could not reply:
- Existing conversation: the visitor message is stored and delivered to the team. The Turkish
messagesays it was forwarded, and forassistant_quota_exhaustedalso says a team member will reply. Read replies from conversation messages. - First message: nothing is stored and no conversation is created. The Turkish
messageasks the visitor to try later.
assistant_unavailable also has two cases. If the turn never started, nothing happened and the message asks the visitor to retry later. If the turn started and then failed, the visitor message was stored and the explanation says it was forwarded to the team. Retrying with the same key does not store it twice and lets the assistant answer it.
type values
type | Errors |
|---|---|
invalid_request_error | 400, 404, 409, 413, 422 |
authentication_error | 401 |
permission_error | 403 |
insufficient_quota | 402 plan_required, 429 assistant_quota_exhausted |
rate_limit_error | 429 rate_limit_exceeded, ai_turn_ceiling, file_download_limit, file_egress_limit |
server_error | 503 |
Response headers
| Header | Purpose |
|---|---|
x-request-id | Request ID, present on every response. Include it when contacting support. |
retry-after | Seconds to wait before retrying. |
x-should-retry | false means do not repeat the same request. OpenAI SDKs respect it automatically. |
x-sone-conversation-id | Conversation ID, included in turn responses and at the start of streams. |
x-sone-error-code | Error code for POST /chat only. Not exposed to browser code. |
Browser code can read x-request-id, retry-after, x-should-retry and x-sone-conversation-id.
Retrying
- Do not retry when
x-should-retry: false. This applies toplan_required,assistant_quota_exhausted,ai_turn_ceiling,idempotency_key_reused,conversation_model_mismatch,conversation_full, andassistant_pausedwhen the message reached the team. - If
Retry-Afteris present withoutx-should-retry: false, wait that long. It is provided forrate_limit_exceeded,conversation_busy,assistant_paused,assistant_unavailable,file_download_limitandfile_egress_limit.ai_turn_ceilingalso includes it, but must not be retried automatically. - For
503withoutRetry-After, or a network failure, resend the same request with the sameIdempotency-Key. Back off for 1, 2, 4 and 8 seconds. The message is not stored twice. See Retries, including the publishable-key network-address exception. conversation_busyis a race: two turns were sent concurrently. Disable sending until the current turn finishes.- Other
4xxerrors require correcting the request.
OpenAI SDKs retry 408, 409, 429 and 5xx twice by default. They respect x-should-retry and wait for retry-after values up to 60 seconds. They do not add Idempotency-Key; pass it in request options: Chat Completions.
Errors during streaming
Key, limit, assistant, conversation and plan checks run before streaming begins, even with "stream": true. Rejections return normal HTTP errors. Once streaming starts, the HTTP status cannot change, so the server writes an error and closes the stream:
- Chat Completions:
data: {"error": {…}}, using the error object above, followed bydata: [DONE]. OpenAI SDKs throw this as an error. - Responses: an
errorevent withtype,code,message,paramandsequence_number, thenresponse.failed. The failed response hasstatus: "failed"and the samecodeandmessageinerror. No[DONE]follows. OpenAI's Node SDK throwsAPIErroronerror, with the code aterror.code; Python delivers an event withtype: "error". - Vercel AI SDK:
{"type":"error","errorText":"…"}, followed bydata: [DONE].useChatchangesstatustoerrorand exposes the text througherror.message.
Possible post-start errors are ai_turn_ceiling if the limit is reached mid-turn, and assistant_unavailable if the turn fails. Messages sent before the error were stored; recover them through GET /conversations/{id}/messages.
What to show visitors
You can display message, but a clear next step is often better. For 429 and 503, say you cannot reply now and ask the visitor to try later. In an existing conversation, ai_turn_ceiling, assistant_quota_exhausted, plan_required or assistant_paused means the message reached your team; explain that the team will reply in this chat. Do not display raw error codes to visitors.