Skip to main content
This document describes how the API handles errors in both standard HTTP requests and streaming connections.

Standard HTTP Errors

All synchronous requests return errors using standard HTTP status codes (4xx/5xx) and a JSON body.

Format

{
  "error": {
    "type": "error_type_string",
    "message": "Human-readable description"
  }
}
  • type: Categorizes the error (e.g., invalid_request_error, insufficient_quota).
  • message: Describes the specific issue.

Common Status Codes

CodeTypeDescription
400invalid_request_errorInvalid input (e.g., missing fields, bad syntax).
401authentication_errorInvalid or missing API key.
402insufficient_quotaInsufficient credits to perform the request.
403inappropriate_contentRequest blocked by content moderation policies.
429rate_limit_exceededToo many requests.
500server_errorInternal server error or upstream provider failure.

Streaming Errors

When using Server-Sent Events (SSE) with stream=true, most requests either succeed or fail before the stream starts (you’ll get a normal HTTP 4xx/5xx response). In rare cases, a request can fail after the initial 200 OK stream connection is established (for example, during late-stage generation). If you want more robust clients, you can also handle these “mid-stream” errors.

Architectural Overview

We strictly separate content generation from system errors:
  • Content: Returned in choices[0].delta (OpenAI-compatible).
  • Errors: Returned as a top-level error object.
This ensures clients can programmatically distinguish between text generation and failure signals without parsing the content itself.

Error Event Format

If an error occurs mid-stream, the API emits a final JSON event with the error field and closes the connection.
data: {
  "error": {
    "type": "error_type_string",
    "message": "Human-readable error description"
  }
}

In SSE, each event is terminated by a blank line. After emitting an error event, the server closes the connection.

Handling Late Failures (e.g., Image Generation)

Some requests, such as image generation with gemini-3-pro-image-preview, may fail late in the process due to content filtering or generation refusal. Instead of a generic 500 error, these are mapped to specific error types to indicate why the request failed. Example: Image Generation Refusal If the model refused to generate the image (for example, the generated image did not pass the provider’s internal moderation), the stream will emit something like this:
data: {
  "error": {
    "type": "inappropriate_content",
    "message": "We got a bad response from the source. Status 403. Error message: Unable to show the generated image. The model could not generate the image based on the prompt provided."
  }
}

Client Implementation

If you want to handle rare late failures, do not treat streaming chunks as simple text appends. Check for a top-level error object and stop processing content when it appears.
import json
import requests

url = "https://api.naga.ac/v1/chat/completions"
headers = {
    "Authorization": "Bearer YOUR_API_KEY",
    "Content-Type": "application/json",
}
payload = {
    "model": "gpt-4o-mini",
    "messages": [{"role": "user", "content": "Say hello in one sentence."}],
    "stream": True,
}

with requests.post(url, headers=headers, json=payload, stream=True) as r:
    r.raise_for_status()

    for line in r.iter_lines(decode_unicode=True):
        if not line:
            continue

        # SSE format: `data: ...`
        if not line.startswith("data:"):
            continue

        data = line[len("data:") :].strip()
        chunk = json.loads(data)

        # 1) CATCH API ERRORS (mid-stream)
        if "error" in chunk:
            raise RuntimeError(chunk["error"]["message"])

        # 2) PROCESS CONTENT
        choices = chunk.get("choices", [])
        if choices:
            content = choices[0].get("delta", {}).get("content")
            if content:
                print(content, end="", flush=True)

print()