# Troubleshooting

Your agent is the first line of support. It can call `carnival_status` and `carnival_logs`, and every error comes with a code, a hint and a page about it.

## First steps

1. On a result with `isError: true`, read `error.code` and `error.hint`, and the page at `error.docs_url`. Fix the input and call again; repeat an unchanged call only when `error.retryable` is true.
2. For a deploy, `carnival_logs` with `deploy_id` shows its steps and its content-check result.
3. For a site, `carnival_status` with `site` shows its status, files and latest deploy, and `carnival_logs` with `site` shows its events and which of its links lead to missing files.
4. Never retry in a loop. When a result gives `retry_after_seconds`, tell the user and try again after that.

## Playbook

| Symptom | Agent does | Typical fix |
|---|---|---|
| Deploy returned `isError` | Read `error.code`/`hint`; `carnival_logs {deploy_id}` | Fix the input; retry only if `retryable` (same `idempotency_key`) |
| Page or image missing on live site | `carnival_logs {site}` → `traffic.top_missing_paths` (only paths the site's own files link to) | Add the file or fix the relative link; update with `site` |
| "Lights are out" (410) | `carnival_status {site}` → `expired`/`ended` | New deploy (new URL); tell the user. Dashboard Redeploy is for live sites only |
| `suspended` / `removed` | `carnival_status {site}` → `status_reason` | Tell the user; don't republish; appeal via support@carnival.dev (a fair-use stop: its `next_step` and `site.suspended` event say it was the traffic, not the content) |
| No free slot | [`LIVE_SITE_LIMIT_REACHED`](https://carnival-staging.dev/docs/errors/LIVE_SITE_LIMIT_REACHED.md) with `live_sites` | Update an existing site, or the user ends one at [the dashboard](https://carnival-staging.dev/dashboard) |
| [`DEPLOYS_PAUSED`](https://carnival-staging.dev/docs/errors/DEPLOYS_PAUSED.md), [`REJECTION_COOLDOWN`](https://carnival-staging.dev/docs/errors/REJECTION_COOLDOWN.md), [`RATE_LIMITED`](https://carnival-staging.dev/docs/errors/RATE_LIMITED.md) | Read `retry_after_seconds` | Tell the user; retry later, never loop |

## Connecting

- **The agent guesses URLs or can't find the sign-in.** Give it the prompt on [Install](https://carnival-staging.dev/docs/install.md). Every endpoint comes from `https://carnival-staging.dev/.well-known/oauth-protected-resource/mcp` and the metadata it lists; [Read this first](https://carnival-staging.dev/muse.md) lists them all.
- **Muse says "Something went wrong" when you add the connector.** Muse reads Carnival's docs before it adds the connector, and that can take a few minutes. Wait a minute and try again. If it keeps failing, email support@carnival.dev with the time you tried.
- **`GET /mcp` returns 405.** That's expected: the server takes POST only, and the 405 means it is up.
- **HTTP 401 from `/mcp`.** No valid access token: the client refreshes its token, or signs in again once the connection has ended (after 30 days unused, or 180 days in all). The `WWW-Authenticate` header names where to start.
- **The agent says Carnival is connected, but calls fail with [`UNAUTHORIZED`](https://carnival-staging.dev/docs/errors/UNAUTHORIZED.md).** The connection was disconnected or has ended. Reconnect Carnival in the client and sign in again; in Muse Code, run `muse mcp login carnival`.
- **HTTP 403 `insufficient_scope`, or [`INSUFFICIENT_SCOPE`](https://carnival-staging.dev/docs/errors/INSUFFICIENT_SCOPE.md).** The connection isn't allowed to publish. Reconnect and allow publishing.
- **Any other HTTP 403 from `/mcp`.** The request has an `Origin` header other than https://carnival-staging.dev: send none.
- **HTTP 413 or 415 from `/mcp`.** Send `Content-Type: application/json` and a body under 8 MiB. Tool calls should be far smaller: at most 4 MiB of files, and about 90 KB on Muse.
- **Muse Code: "no MCP server named `carnival` is configured".** Muse Code reads its servers from `~/.config/muse/settings.json`, not from a project's `.mcp.json`. Add the `carnival` entry there, as [Install](https://carnival-staging.dev/docs/install.md#muse-code) shows, and run `muse mcp login carnival` again.
- **Muse Code: the browser tab hangs after Allow.** Close it; the login is done. Then ask Muse Code to call `carnival_status`.
- **Sign-in is refused.** Accounts are for people 18 or older, signing up from the US, Canada or Mexico. If sign-ups are paused or Carnival is full for the day, try again later.
- **"This account can't connect agents."** The account is suspended or locked, and the page says which. For a suspension, the email Carnival sent gives the reasons; to unlock a locked account, write to support@carnival.dev.
- **"Carnival has blocked this app."** Carnival doesn't accept connections from that app. Connect from another client.

## Deploy failed

Read `error.code` and `error.hint`. The common causes:

- **The wrong folder.** [`MISSING_INDEX_HTML`](https://carnival-staging.dev/docs/errors/MISSING_INDEX_HTML.md): send the contents of the build's output folder, with `index.html` at the top level, not the folder itself. [`SERVER_CODE_NOT_ALLOWED`](https://carnival-staging.dev/docs/errors/SERVER_CODE_NOT_ALLOWED.md): run the build and send only its output; [Frameworks](https://carnival-staging.dev/docs/frameworks.md) names each framework's folder.
- **A file type Carnival doesn't host.** [`DISALLOWED_FILE_TYPE`](https://carnival-staging.dev/docs/errors/DISALLOWED_FILE_TYPE.md): only the types in the `carnival_deploy` description, and no scripts in SVGs. Embed video and audio from YouTube or Vimeo.
- **Paths.** [`INVALID_PATH`](https://carnival-staging.dev/docs/errors/INVALID_PATH.md), [`DUPLICATE_PATH`](https://carnival-staging.dev/docs/errors/DUPLICATE_PATH.md): relative paths like `img/logo.webp`, of letters, digits and `- _ . ~ /`, with no dotfiles; each path once, ignoring case.
- **Encoding.** [`INVALID_ENCODING`](https://carnival-staging.dev/docs/errors/INVALID_ENCODING.md): images, fonts and PDFs as base64 with `"encoding": "base64"`, text as UTF-8, and each extension matching the real format. [`HASH_MISMATCH`](https://carnival-staging.dev/docs/errors/HASH_MISMATCH.md): `sha256` is the lowercase hex SHA-256 of the decoded bytes; or leave it out.
- **Too big.** [`FILE_TOO_LARGE`](https://carnival-staging.dev/docs/errors/FILE_TOO_LARGE.md) (4 MiB a file), [`SITE_TOO_LARGE`](https://carnival-staging.dev/docs/errors/SITE_TOO_LARGE.md) (25 MiB), [`TOO_MANY_FILES`](https://carnival-staging.dev/docs/errors/TOO_MANY_FILES.md) (250 files): compress images (WebP or AVIF), remove unused files, bundle scripts and stylesheets. [Limits](https://carnival-staging.dev/docs/limits.md) has every number.
- **Too much in one call.** [`PAYLOAD_TOO_LARGE`](https://carnival-staging.dev/docs/errors/PAYLOAD_TOO_LARGE.md), [`TOO_MANY_FILES_IN_CALL`](https://carnival-staging.dev/docs/errors/TOO_MANY_FILES_IN_CALL.md): stage the files over several calls with `finalize=false` (up to 72 a call, stylesheets first), keep the `deploy_id`, then send the last 30 or fewer with `finalize=true`. The recipe is in [Read this first](https://carnival-staging.dev/muse.md).
- **A staged upload.** [`MISSING_CONTENT`](https://carnival-staging.dev/docs/errors/MISSING_CONTENT.md), [`MISSING_PARTS`](https://carnival-staging.dev/docs/errors/MISSING_PARTS.md): send what `missing` or `missing_parts` lists, with the same `deploy_id`. [`DEPLOY_EXPIRED`](https://carnival-staging.dev/docs/errors/DEPLOY_EXPIRED.md) (60 minutes from the first call), [`DEPLOY_NOT_FOUND`](https://carnival-staging.dev/docs/errors/DEPLOY_NOT_FOUND.md): start again without `deploy_id`, reusing uploaded files as `{path, sha256}`. [`DEPLOY_ALREADY_FINALIZED`](https://carnival-staging.dev/docs/errors/DEPLOY_ALREADY_FINALIZED.md): update the site with `site` instead.
- **Arguments.** [`INVALID_ARGUMENTS`](https://carnival-staging.dev/docs/errors/INVALID_ARGUMENTS.md): `error.field` and `error.reason` name the problem. [`IDEMPOTENCY_CONFLICT`](https://carnival-staging.dev/docs/errors/IDEMPOTENCY_CONFLICT.md): use a new key for every new call. An uncoded `Input validation error: …` means the arguments don't match the tool's schema: see [Tools](https://carnival-staging.dev/docs/tools.md).
- **The site.** [`SITE_NOT_FOUND`](https://carnival-staging.dev/docs/errors/SITE_NOT_FOUND.md): `carnival_status` lists the account's sites; pass the exact slug, or omit `site` to create one. [`SITE_NOT_LIVE`](https://carnival-staging.dev/docs/errors/SITE_NOT_LIVE.md): the site closed (see [The lights are out](#expired)).

## Timeouts

- **A call timed out, or returned [`INTERNAL_ERROR`](https://carnival-staging.dev/docs/errors/INTERNAL_ERROR.md).** Repeat the identical call with the same `idempotency_key` (or `deploy_id`): a call that finished returns its original result, never a second site. If it keeps failing, stop and give the user the `request_id`.
- **On Muse, a call fails without a Carnival error.** Keep each call's arguments under about 90 KB: a bigger call may fail before it reaches Carnival. Stage files over several calls and send big files in pieces.

## Content rejected

[`CONTENT_REJECTED`](https://carnival-staging.dev/docs/errors/CONTENT_REJECTED.md) means the content check stopped the publish, and `filter.reasons` says why:

- **A house rule** (`category: "house_rule"`, with `rule`, `path`, `line` and `fix`): apply the fix and call again with the same `deploy_id`, only the corrected files and `finalize=true`, before the staged upload expires (60 minutes after its first call). [Frameworks](https://carnival-staging.dev/docs/frameworks.md#house-rules) lists the house rules.
- **A content-policy category** (only `category`): the site may break the [content policy](https://carnival-staging.dev/content-policy.md). Don't reword, split or disguise the content to get past the check. Tell the user; they can appeal at support@carnival.dev with the `request_id`.
- **`checks_unavailable`:** Carnival couldn't finish checking the site, and nothing needs to change. Call again with the same `deploy_id` in about 60 seconds.

A site can also go live with notices in `filter.reasons` or `warnings`: Carnival may review it. Apply the fixes as an update (`site=<slug>`) so it isn't taken down.

After 5 rejections in one day (UTC), publishing pauses for 24 hours: [`REJECTION_COOLDOWN`](https://carnival-staging.dev/docs/errors/REJECTION_COOLDOWN.md).

## No free slot

[`LIVE_SITE_LIMIT_REACHED`](https://carnival-staging.dev/docs/errors/LIVE_SITE_LIMIT_REACHED.md): all 3 live-site slots are in use, and `live_sites` lists them. Update one of those sites by passing its slug as `site` (no extra slot), or ask the user to end one at [the dashboard](https://carnival-staging.dev/dashboard). Agents can't end sites.

## Page or image missing

`carnival_logs` with `site` returns `traffic.top_missing_paths`: the missing files the site's own pages link to, with counts (other not-found requests count as `(other)`). The counts are estimates and can trail by about a minute.

- Add the missing file, or fix the link, and update the site with `site` and only the changed files.
- Paths are case-sensitive: `Logo.png` and `logo.png` are different files.
- `/about` serves `about.html`, or redirects to `/about/` for `about/index.html`.
- An unknown address gets the nearest `404.html`, if the site has one.
- A single-page app that routes in the browser needs `spa: true` on `carnival_deploy`, so its page addresses serve `index.html`.

## An update doesn't show

- An update goes live within about 12 seconds. Pages revalidate on every visit, so a reload shows it.
- Files whose names end in a build hash (like `index-BxK3f9aQ.js`) are cached by browsers for a year. Build tools rename them when they change; a file you change by hand that has such a name (like `photo-20240101.jpg`) needs a new name, and its links updated.

## The lights are out (410)

The site's address says the lights are out: `carnival_status` with `site` shows `expired` or `ended`. Its files are deleted, and the address can't come back. Publish again without `site` (a new site, a new URL, 7 new days) and tell the user. The dashboard's Redeploy works on live sites only.

## Suspended or removed

`carnival_status` with `site` shows `status_reason`: the category and how to appeal. Tell the user. Don't republish the content, at that address or a new one, and don't open another account. The user can appeal at support@carnival.dev.

If Carnival took the site offline for its traffic (fair use on the free plan), its `next_step` and its `site.suspended` event say so: it was the traffic, not the content.

[`ACCOUNT_SUSPENDED`](https://carnival-staging.dev/docs/errors/ACCOUNT_SUSPENDED.md) means the whole account can't publish: the user checks Carnival's email or writes to support@carnival.dev.

## Paused or rate limited

[`DEPLOYS_PAUSED`](https://carnival-staging.dev/docs/errors/DEPLOYS_PAUSED.md) (maintenance; live sites are fine), [`RATE_LIMITED`](https://carnival-staging.dev/docs/errors/RATE_LIMITED.md) (`error.limit` names the limit) and [`REJECTION_COOLDOWN`](https://carnival-staging.dev/docs/errors/REJECTION_COOLDOWN.md): read `error.retry_after_seconds`, tell the user when publishing works again (in their own time zone), and try again after that. Never retry in a loop.

For a publish limit, combine the remaining changes into one update. For `new_sites_per_day`, update an existing site instead. [Limits](https://carnival-staging.dev/docs/limits.md) has the numbers.

## Still stuck

Email support@carnival.dev with the `request_id` from the error, the site's URL and what the agent tried. A person replies within 2 business days. See [Support](https://carnival-staging.dev/support.md).
