Skip to content
Docs navigation: System Zero / Errors

Errors

DocsSystem ZeroErrors Updated

Use error.code to identify a refusal and error.retryable to decide whether to retry.

decide.sh
# Set SYSTEM_ZERO_API_KEY to your API key before running this example.
# Generate once per logical decision; reuse this key when retrying.
idempotency_key="$(uuidgen 2>/dev/null \
  || cat /proc/sys/kernel/random/uuid 2>/dev/null \
  || openssl rand -hex 16 2>/dev/null \
  || python3 -c 'from uuid import uuid4; print(uuid4())' 2>/dev/null)"
cat > request.json <<'EOF'
{
  "model": "system-zero",
  "state": "The blender I ordered arrived with a cracked jar.",
  "questions": {
    "damaged": {
      "type": "boolean",
      "instructions": "Did the item arrive damaged?"
    }
  }
}
EOF
# Headerless error responses require Python 3 to read error.code.
# If x-should-retry is present, resend only when x-should-retry is true. If the
# header is absent, resend on 429, or on 409 and 5xx only with a retryable
# error.code. No answer also retries. Wait Retry-After plus up to 10 %,
# otherwise a random wait doubling from 1 s to 30 s. Stop if Retry-After is over
# 60 s. Also stop when a 429 has no Retry-After, or a 5xx has x-should-retry but
# no Retry-After.
random() { od -An -N4 -tu4 /dev/urandom | tr -d ' '; }
# Stop resending after 10 minutes.
start=$(date +%s) attempt=0
while :; do
  : "${SYSTEM_ZERO_API_KEY:?set it first}"
  : "${idempotency_key:?could not make one}"
  rm -f reply.json
  out=$(curl https://api.rightnowai.co/v1/system-zero/decide \
    --max-time 130 -sS -o reply.json -D - -w '%{http_code}' \
    -H "Authorization: Bearer $SYSTEM_ZERO_API_KEY" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: $idempotency_key" \
    -d @request.json)
  code=$(printf '%s' "$out" | tail -c 3)
  retry_header=$(printf '%s\n' "$out" \
    | grep -i '^x-should-retry:' | tail -n 1)
  retry=$(printf '%s\n' "$retry_header" \
    | sed 's/^[^:]*:[[:space:]]*//;s/[[:space:]]*$//')
  after=$(printf '%s\n' "$out" | grep -i '^retry-after:' \
    | tail -n 1 | sed 's/^[^:]*:[[:space:]]*//;s/[[:space:]]*$//')
  case $after in *[!0-9]*|'') after= ;; esac
  if [ -z "$retry_header" ]; then
    case $code in
      000|429) ;;
      409|5??)
        error_code=$(python3 -c 'import json, sys
try:
    print(json.load(sys.stdin).get("error", {}).get("code", ""))
except (ValueError, AttributeError):
    pass' < reply.json 2>/dev/null) || break
        case $code:$error_code in
          409:idempotency_conflict) ;;
          409:upload_in_use) ;;
          409:session_busy) ;;
          5??:service_unavailable) ;;
          5??:system_zero_unavailable) ;;
          5??:billing_settlement_error) ;;
          5??:idempotency_unavailable) ;;
          5??:limiter_unavailable) ;;
          5??:internal_error) ;;
          5??:maintenance) ;;
          5??:revoke_notice_unavailable) ;;
          *) break ;;
        esac ;;
      *) break ;;
    esac
  else
    [ "$retry" = true ] || break
    case $code in 4??|5??) ;; *) break ;; esac
  fi
  if [ -n "$after" ]; then
    after=$(printf '%s' "$after" | sed 's/^0*//')
    after=${after:-0}
    [ "$after" -le 60 ] || break
    ms=$(( after * 1000 + $(random) % (after * 100 + 1) ))
  else
    [ "$code" != 429 ] || break
    if [ -n "$retry_header" ]; then
      case $code in 5??) break ;; esac
    fi
    cap=$(( attempt < 5 ? 1000 << attempt : 30000 ))
    ms=$(( $(random) % (cap + 1) ))
  fi
  [ $(( $(date +%s) - start + ms / 1000 )) -lt 600 ] || break
  sleep "$(( ms / 1000 )).$(printf '%03d' $(( ms % 1000 )))"
  [ $(( $(date +%s) - start )) -lt 600 ] || break
  attempt=$(( attempt + 1 ))
done
echo "HTTP $code"
cat reply.json 2>/dev/null

Error body

A request refusal returns an HTTP status and an error envelope. This example shows the held-image refusal.

error.json
JSON
{
  "error": {
    "message": "Images are not available yet. Send the request without the image attachment.",
    "type": "not_found_error",
    "param": null,
    "code": "image_not_available",
    "retryable": false
  },
  "request_id": "request-id-from-response"
}
error.message
A readable description of the refusal.
error.type
The error category.
error.param
The affected field, or null.
error.code
The code your application should handle.
error.retryable
A boolean: true permits an automatic retry; false stops automatic retries.
error.details
Optional machine-readable context, such as a cause or reset.
request_id
The request identifier to include when contacting support.

An HTTP 200 can contain a refusal under an individual question in answers. Check the entries as well as the HTTP status.

Error codes

Held marks an input or route this release does not serve. A held code does not make its feature available.

StatusCodeMeaningRetryable
400Code: idempotency_key_reuseUse the original body with this key, or use a new key for changed work.No automatic retry.
400Code: invalid_idempotency_keyUse a nonblank Idempotency-Key with valid ASCII characters within the accepted length.No automatic retry.
400Code: invalid_requestCorrect the JSON, field names, types or encoding before resending.No automatic retry.
400Code: invalid_trace_headerCorrect or remove X-Client-Request-Id; its value must be nonblank ASCII within the accepted length.No automatic retry.
401Code: invalid_api_keyAuthorization is missing, malformed or unknown; a Playground credential is not accepted as a public bearer key. Use a valid System Zero API key.No automatic retry.
403Code: account_suspendedThe account is suspended, blocked or waiting for access. Contact support.No automatic retry.
403Code: auth_errorThe API key is revoked or blocked. Replace the key; this response uses authentication_error as its type.No automatic retry.
403Code: https_requiredUse the HTTPS base URL.No automatic retry.
404Code: audio_not_availableHeld. Audio is not available yet. Send the request without the audio attachment. Remove the audio attachment.No automatic retry.
404Code: committee_not_availableHeld. This route is not available. Use standard route.No automatic retry.
404Code: deliberate_not_availableHeld. This mode is not available. Use standard mode.No automatic retry.
404Code: document_controls_not_availableHeld. Documents with control characters are not available yet. Remove the control characters and send it again. Document attachments remain unavailable, including after control characters are removed.No automatic retry.
404Code: document_not_availableHeld. Documents are not available yet. Send the request without the document attachment. Send document contents as state text without an attachment.No automatic retry.
404Code: document_pictures_not_availableHeld. Pictures inside documents are not available yet. Send the document without pictures, or as text. Document attachments remain unavailable, including after pictures are removed.No automatic retry.
404Code: image_not_availableHeld. Images are not available yet. Send the request without the image attachment. Remove the image attachment.No automatic retry.
404Code: long_context_not_availableHeld. This route is not available. Use a shorter stateless text request; sessions remain held.No automatic retry.
404Code: long_recording_not_availableHeld. This input type is not supported. Remove the long recording.No automatic retry.
404Code: model_not_foundThe requested model is not offered. Choose the alias or an available pinned version.No automatic retry.
404Code: unknown_endpointThe route is unavailable. Check the base URL and path; this response does not mean the API key is invalid.No automatic retry.
404Code: video_not_availableHeld. This input type is not supported. Remove the video attachment.No automatic retry.
405Code: method_not_allowedUse a method from the Allow response header.No automatic retry.
409Code: idempotency_conflictThe same key and body is still running. Wait and retry with that key.Yes. Follow the response wait.
409Code: idempotency_replay_unavailableThe request completed, but the stored answer is unavailable. details.original_status records the original status. A new key starts new work; this is not a replay of the old answer.No automatic retry.
413Code: payload_too_largeReduce the whole request body.No automatic retry.
413Code: questions_too_largeSend fewer or shorter questions.No automatic retry.
413Code: state_too_largeShorten the state or reduce nesting.No automatic retry.
413Code: state_too_large_unguardedShorten or split the state.No automatic retry.
422Code: injection_suspectedRemove embedded instructions from the input and send changed input.No automatic retry.
422Code: invalid_criteriaUse the supported criteria shape and the served text range.No automatic retry.
422Code: question_too_largeShorten the affected question.No automatic retry.
429Code: capacity_exhaustedWait for Retry-After; retry only with bounded client backoff.Yes. Follow the response wait.
429Code: concurrency_limit_exceededThe account already has its allowed work in flight. Follow Retry-After and reduce concurrency; details include max_concurrent.Yes. Follow the response wait.
429Code: monthly_cap_reachedThe workspace reached its monthly decision cap. Follow resets_at and Retry-After; details include monthly_request_cap and used.Yes. Follow the response wait.
429Code: playground_daily_limitThe Playground reached its daily limit. Wait for resets_at; details include daily_limit.Yes. Follow the response wait.
429Code: rate_limit_exceededWait for Retry-After and pace requests to the returned limits.Yes. Follow the response wait.
429Code: workspace_limit_exceededWait for Retry-After and reduce the workspace's concurrent work or input load.Yes. Follow the response wait.
500Code: internal_errorAn unexpected failure was caught. Retry after the stated delay; contact support with the request ID if it persists.Yes. Follow the response wait.
503Code: idempotency_unavailableReplay protection cannot answer. Retry with the same Idempotency-Key after the wait.Yes. Follow the response wait.
503Code: limiter_unavailableThe limiting service cannot answer. Retry after the stated delay.Yes. Follow the response wait.
503Code: maintenanceThe API is in maintenance. Wait for Retry-After.Yes. Follow the response wait.
503Code: service_unavailableWait for Retry-After; keep the request ID if the failure persists.Yes. Follow the response wait.
503Code: system_zero_unavailableWait for Retry-After and retry when retryable is true.Yes. Follow the response wait.
504Code: system_zero_timeoutShorten the work or inspect the outcome; do not automatically replay unchanged.No automatic retry.

While the API is unlisted, a call without a valid key for an active account receives 404 unknown_endpoint. Check the key, workspace access, API host and route.

Retries

x-should-retry matches error.retryable. Stop automatic retries when it is false, including 504 system_zero_timeout.

When a response permits a retry, wait for Retry-After-Ms in milliseconds or Retry-After in seconds. Prefer Retry-After-Ms when both are present.

Keep the decision's Idempotency-Key and JSON body. An idempotency_conflict means the same work is still running; wait before retrying with that key.

After a quiet period, a model pool can start on demand. A cold start can outlast a client's retry window; follow the response flags and wait.

Get help

For a refusal that persists, use Contact and include the response's X-Request-Id.