Skip to main content

Error Reference

Every error code the API returns, what caused it, and exactly how to fix it. Every JSON body below is verbatim from the production handler.

All error responses include an X-Request-Id header. Include it when contacting hello@chart-output.com.

400 Bad Request

The request body is not valid JSON, or the chart spec fails schema validation. The details array always identifies the exact failing field — no guessing required.

Invalid chart specification (Zod validation failure)

json
{ "error": "Invalid chart specification", "details": [ { "path": "data.labels", "message": "At least 1 label is required" }, { "path": "width", "message": "Number must be less than or equal to 4000" } ] }

Malformed JSON in request body

json
{ "error": "Invalid JSON in request body" }

URL too long (GET endpoint only)

json
{ "error": "URL too long", "message": "URL exceeds 2000 characters. Use POST for complex charts." }

Reading details[].path

Each path uses dot notation and maps directly to a key in your JSON spec. Array indices appear as numbers.

path valueMeaning
typeRoot-level chart type; must be line, bar, pie, doughnut, radar, or polarArea
data.labelsThe labels array — must have 1–1000 entries
data.datasets.0.datadata array of the first dataset (index 0)
width / heightRoot-level dimensions; must be integers in the range 100–4000
(empty string)Error is at the root of the spec — usually a missing required field

Common causes

  • Missing type or data — both are always required
  • Invalid chart type or format string — values are case-sensitive ("Line" fails, "line" works)
  • Dimensions outside 100–4000 px, or scale outside 1–4
  • Empty data.labels or data.datasets, or more than 1000 labels / 20 datasets / 1000 data points per dataset
  • Trailing commas or single-quoted strings — standard JSON only
  • Non-HTTPS header.logoUrl — only HTTPS URLs are accepted
  • Invalid base64 encoding in the chart or c GET parameter

Fix

Read details[].path and details[].message. Every field name is a direct reference to your spec JSON. The Chart Studio playground highlights the offending key inline.

401 Unauthorized

An Authorization header was present but the key was invalid, malformed, or revoked. Requests with no auth at all return 200 at anonymous/starter limits — not 401.

Invalid or revoked API key

json
{ "error": "Invalid API key" }

Malformed Authorization header

The header was present but did not start with Bearer (with the trailing space).

json
{ "error": "Invalid Authorization format. Use: Bearer <api_key>" }

Fix

CauseFix
Typo in keyCopy the key exactly from API Keys in your dashboard
Wrong prefix formatHeader must be Authorization: Bearer pk_live_… (note the space)
Key was deletedCreate a new key in the dashboard
Using a pk_test_ key against production dataSandbox keys work for renders; they are not restricted by environment

403 Forbidden

The API key is valid but the operation is not permitted for the current plan. Check plan and upgradeUrl in the response body.

Subscription required (trial expired or account lapsed)

json
{ "error": "Subscription required. Please upgrade to continue.", "plan": "expired", "upgradeUrl": "/app/usage-billing" }

Trial plan — non-PNG format requested

Trial accounts are restricted to PNG output only.

json
{ "error": "Trial includes PNG output only. Upgrade for WebP, SVG, JPEG, and PDF.", "plan": "trial", "upgradeUrl": "/pricing" }

PDF output — Business plan required

PDF output requires the Business plan (pro or business internally).

json
{ "error": "PDF output requires the Business plan", "plan": "starter", "upgradeUrl": "/pricing" }

Fix

CauseFix
Trial + non-PNG formatUse "format": "png", or upgrade
Expired subscriptionRenew or upgrade at /app/usage-billing
PDF on Starter/Pro tierUpgrade to Business, or use PNG + embed in a PDF library (see the PDF guide)

429 Too Many Requests

Either per-window rate limiting or render quota exhaustion. The two are distinguished by the shape of the body.

Rate limit — 100 requests per 15 minutes

json
{ "error": "Rate limit exceeded", "retryAfter": 120 }

Headers also present on 429 rate-limit responses:

  • Retry-After — Seconds until the window resets
  • X-RateLimit-Limit — Maximum requests per window (100)
  • X-RateLimit-Remaining — Requests remaining (0 on 429)
  • X-RateLimit-Reset — ISO 8601 timestamp of when the window resets

Billing-period quota exceeded

json
{ "error": "Render quota exceeded for your billing period. Upgrade or wait for renewal.", "currentUsage": 100000, "limit": 100000, "plan": "starter" }

Trial render cap reached (500 renders)

json
{ "error": "Trial render limit reached (500 renders). Upgrade to continue.", "plan": "trial", "upgradeUrl": "/app/usage-billing" }

Fix

CauseFix
Rate limit (100/15 min)Wait Retry-After seconds, or distribute requests over time
Billing quotaUpgrade plan or wait for next billing cycle
Trial cap (500)Upgrade to Starter or higher at /app/usage-billing

500 Internal Server Error

Server error during rendering. This is never caused by your spec — it means something went wrong on our side.

json
{ "error": "Internal server error" }

Email hello@chart-output.com with the X-Request-Id from the response header and we will investigate.