# Errors

> Every VectorFast Render error code with its HTTP status, what causes it, and how to fix it, for the REST API, signed image URLs, and the MCP server.

Canonical URL: https://vectorfast.ai/render/docs/errors
Markdown URL: https://vectorfast.ai/render/docs/errors.md
Last modified: 2026-10-30

**Short answer:** every error from `/v1/*` and `/i/*` is JSON shaped as `{"error": {"code", "message", "docs"}}`. `code` is stable and listed below; `message` names the field or rule that failed and never repeats the value you sent; `docs` links to the matching section of this page.

```json
{
  "error": {
    "code": "invalid_params",
    "message": "title: Too big: expected string to have <=120 characters",
    "docs": "https://vectorfast.ai/render/docs/errors#invalid_params"
  }
}
```

Error responses are never cached (`Cache-Control: no-store`). In the MCP server, parameter and business errors come back as tool results with `isError: true` and the same message; authentication failures are HTTP `401`.

| Code                                                  | Status                  | Retry?                   |
| ----------------------------------------------------- | ----------------------- | ------------------------ |
| [`invalid_params`](#invalid_params)                   | 400, 405, 409, 413, 415 | No, fix the request      |
| [`invalid_signature`](#invalid_signature)             | 403                     | No                       |
| [`unauthorized`](#unauthorized)                       | 401                     | No, fix the key          |
| [`insufficient_credits`](#insufficient_credits)       | 402                     | After topping up         |
| [`template_not_found`](#template_not_found)           | 404                     | No                       |
| [`brand_kit_not_found`](#brand_kit_not_found)         | 404                     | No                       |
| [`brand_kit_limit_reached`](#brand_kit_limit_reached) | 403                     | No                       |
| [`brand_kit_conflict`](#brand_kit_conflict)           | 409                     | Yes, after re-reading    |
| [`not_found`](#not_found)                             | 404                     | No                       |
| [`rate_limited`](#rate_limited)                       | 429                     | Yes, after `Retry-After` |
| [`render_failed`](#render_failed)                     | 500, 502                | Yes, with backoff        |
| [`render_timeout`](#render_timeout)                   | 504                     | Yes, with backoff        |
| [`render_unavailable`](#render_unavailable)           | 503                     | Yes, with backoff        |

## invalid\_params [#invalid_params]

The request is malformed or breaks a rule: a body that is not JSON, a missing required parameter, a string over its length limit, a size the template does not support, a parameter given twice in a signed URL, or an unsupported format. The same code covers a body over 256 KiB (`413`), a logo over 5 MB or 4096×4096 (`400`), a logo `Content-Type` that is not PNG, JPEG, SVG, or multipart (`415`), a wrong HTTP method (`405`), and an `Idempotency-Key` reused with a different body (`409`).

**Fix:** read `message`, which names the field (for example `title`) and the rule. Check the template's parameter table under [Templates](/render/templates).

## invalid\_signature [#invalid_signature]

A signed image URL is missing `sig`, has a malformed one, or any part of the URL changed after signing: a parameter, the template, the format, the size, or the key id.

**Fix:** use the URL exactly as it was returned, or sign it again with the algorithm in [Signed URLs](/render/docs/signed-urls).

## unauthorized [#unauthorized]

The `Authorization` header is missing, is not `Bearer vf_live_…`, or names a key that does not exist or was revoked. The response carries a `WWW-Authenticate: Bearer` header.

**Fix:** check the key and create a new one if it was revoked. See [Authentication](/render/docs/authentication).

## insufficient\_credits [#insufficient_credits]

Reserved for when billing is connected: the request needs a new render and the account has no credits left, no credit pack, and no opted-in overage. The response will include an upgrade link. Billing is not connected in early access, so this code is not returned yet.

**Fix:** once billing launches, upgrade, buy a credit pack, or enable overage on Growth or Scale.

## template\_not\_found [#template_not_found]

The template id is not in the catalog, or a pinned major version (`launch-post@2`) does not match the current one.

**Fix:** list templates with `GET /v1/templates` or the MCP `list_templates` tool, and pin the current major version.

## brand\_kit\_not\_found [#brand_kit_not_found]

The brand kit id does not exist on your account, the pinned version does not exist, or the kit was deleted. Ids from other accounts always return this code.

**Fix:** list your kits with `GET /v1/brand-kits` or leave `brand_kit` out to use your default kit.

## brand\_kit\_limit\_reached [#brand_kit_limit_reached]

Creating the brand kit would exceed your plan's limit (Free 1, Starter 3, Growth 10, Scale 30).

**Fix:** delete a kit you no longer use, or upgrade once paid plans are available.

## brand\_kit\_conflict [#brand_kit_conflict]

The brand kit changed while your update or logo upload was running, so your change was not saved.

**Fix:** read the kit again and repeat the update or upload.

## not\_found [#not_found]

The path under `/v1/` does not exist.

**Fix:** compare the path with the [REST API reference](/render/docs/rest-api).

## rate\_limited [#rate_limited]

The API key made more than 60 requests in 60 seconds, or more than 3 logo uploads in a minute or 10 in an hour.

**Fix:** wait for the number of seconds in `Retry-After`, then retry. Spread bursts or use more than one key per integration if you need more throughput.

## render\_failed [#render_failed]

The renderer could not produce the image (`500`), or fonts could not be loaded from Google Fonts (`502`). For logo uploads, the pipeline or storage failed.

**Fix:** retry with exponential backoff. If one parameter set fails every time, contact [contact@holengen.com](mailto:contact@holengen.com) with the template id and time of the request; do not send API keys.

## render\_timeout [#render_timeout]

The render took longer than the time budget.

**Fix:** retry with backoff. Shorter text and smaller sizes render faster.

## render\_unavailable [#render_unavailable]

The service is not configured or a dependency, such as the database or the signing secret, is unavailable.

**Fix:** retry with exponential backoff.
