# Troubleshooting

> Failure-mode policy for coding agents: what to fix yourself, what to relay, and what every Tarout error code means

# Troubleshooting

> **Preflight - check auth first.** Run `tarout whoami --json`. If it does not
> return `success: true`, authenticate with the table in
> [start.md](https://tarout.sa/docs/for-ai/start.md)
> before running anything on this page - every command below fails without a
> credential, and the failure reads like a broken deploy rather than a missing
> login.

The governing rule: **when a deploy fails, fix it yourself and redeploy.** Do not
stop and ask, and do not retry blindly. You get up to 3 fix attempts before
reporting back.

## Build or deployment failure

A run ending `BUILD_FAILED` or `DEPLOYMENT_FAILED` gives you everything you need:

```sh
tarout deploy:logs <deployment-id> --follow
```

Read `error.details.errorAnalysis.suggestedFixes` from the envelope as well, then
fix the project:

| Symptom | Fix |
|---|---|
| Missing dependency, or the build can't resolve one | Install it, or commit the lockfile |
| App starts then dies, or the health check never passes | Make the app listen on the `PORT` environment variable |
| "No start script" / wrong entrypoint | Add or fix the production start script |
| Crash referencing a config value | Set it: `tarout env <app> set KEY=VALUE` |
| Upload rejected as too large | Prune `node_modules`, build output, caches, and logs |

Then redeploy. Stop and report only when the same error survives a fix with
nothing left to change, or the fix needs something only the user has (external
credentials, a payment).

## Error codes

### `NEEDS_UPGRADE`

The org has no slot for what you asked for. Run the upgrade flow in
[billing.md](https://tarout.sa/docs/for-ai/billing.md) directly - the checkout page Tarout opens IS
the user's approval step. Don't pre-ask in chat, and don't silently retry.

### `AUTH_ERROR` / `UNAUTHORIZED`

Re-authenticate **from the project root**, then resume:

```sh
tarout whoami --json          # check "scope" first
tarout login --token <YOUR_API_KEY>
# or, with no key to hand:
tarout login
```

`whoami`'s `scope` tells you which credential is in effect:

| `scope` | Meaning |
|---|---|
| `project` | `.tarout/auth.json` at or above the working directory - the normal case |
| `global` | The machine-wide login. Fine, but a project credential would win over it |
| `env` | A `TAROUT_TOKEN` in the environment, the lowest-precedence layer |
| `none` | Not authenticated |

Running `tarout login` from the project root writes `./.tarout/auth.json` and
takes effect immediately. If the second attempt still fails, stop and ask the
user - do not loop.

> If `whoami` shows a different account than the user expects, a
> `.tarout/auth.json` further up the tree is winning. `tarout whoami
> --global-auth` ignores the project layer for one command so you can compare.

**If the user handed you a key and it was rejected, stop there.** Do not carry
on under whatever other credential happens to be authenticated - a
`.tarout/auth.json` in the working directory outranks the global login, so
"just use the one that works" is how a deploy lands in a different customer's
organization. The supplied key names the intended account. Report that it was
rejected, say which account `whoami` reports instead, and wait.

A rejection is not proof the key is revoked or expired (agent keys have no
expiry). The server has reasons the CLI cannot see. Say "the key was rejected",
not "the key is revoked".

### `FORBIDDEN` - "requires an interactive signed-in session"

**This is never an expired credential. Do not re-authenticate; it cannot help.**

An API key has the same authority as a browser sign-in over the account's own
resources - deploys, storage, databases, domains, AI Gateway keys, billing,
members. Exactly three things are refused to an API key, by design:

1. managing API keys themselves (create / rotate / delete / enable),
2. approving your own approval request,
3. platform administration.

Report it and point the user at the dashboard.

### `NEEDS_APPROVAL:<id>`

Not an error to fix. If the user's key is **operator** tier (the dashboard
default), destructive and critical actions create a pending approval instead of
running: deleting an app, database, bucket, domain, or project, terminating a
VM, SQL that drops, deletes, truncates, or alters, and anything that spends
money or moves live traffic. Everything else runs straight away, including
ordinary SQL and removing a single environment variable or file. Tell the user
to approve or deny it on the
dashboard's Agent page, then poll:

```sh
tarout call approvals.get --input '{"id":"<id>"}'
```

Terminal statuses: `executed` (approved and performed - continue), `denied`,
`expired`, or `failed` (approved but the action itself errored - read
`resultSummary`). Retrying the original call while a request is pending returns
the same approval id; it does not create duplicates.

### `AGENT_READ_ONLY:` / `AGENT_SCOPE:`

The key carries a permission tier. `AGENT_READ_ONLY:` means every mutation is
refused. `AGENT_SCOPE:` means the call is outside the key's access areas (for
example a key scoped to Applications + Databases calling `domain.create`).

**Do not retry either.** Tell the user to issue an operator or full-access key,
or widen the access areas, at `/dashboard/agent/keys`.

### `NO_DEDICATED_HOST` / `DEDICATED_HOST_FULL`

Both mean the Pro (dedicated) host could not take the app - **not** that the
plan is wrong or the account is broken.

`NO_DEDICATED_HOST`: the host is not ready yet. A background sweep provisions
it automatically, so retry once after a few minutes. If it still fails, report
it - the host needs an operator, and nothing you can run from the CLI fixes it.

`DEDICATED_HOST_FULL`: the host is at its app limit. The user's options are
deleting an app or moving up a size; both are their call, so ask.

**Do not try to repair the platform's own state.** Resuming, retrying, or
finalizing a server migration is not a fix for this and can make it worse.
Report the error and stop.

### `DEPLOYMENT_TIMEOUT`

Do not retry blindly. Show the user the deployment ID and offer
`tarout deploy:status <id>` so they can decide.

### AI Gateway: `404` `MODEL_NOT_FOUND`

A chat completion returned HTTP `404` with `error.type` set to
`MODEL_NOT_FOUND` and this message:

```text
Model <id> is not offered. Available models: <comma-separated ids>
```

The request's `model` is not in the catalog: a typo, or a model that has been
removed. Removed models are rejected, never redirected to a different model.
Set `model` to one of the IDs in the message, or list what is available now:

```sh
tarout ai models
curl https://tarout.sa/api/ai/v1/models -H "Authorization: Bearer $TAROUT_API_KEY"
```

**Do not create a new key to fix this.** Gateway keys are not tied to a model:
one key calls every model in the catalog. The old `403` "API key is scoped to
model" error no longer exists, so a key never needs replacing to reach another
model.

## Always ask first

- `tarout deploy:rollback`
- `tarout deploy:cancel`
- `tarout apps delete`, `tarout db delete`, `tarout storage delete`
- revealing environment variables (`tarout env <app> reveal KEY`)
- destructive SQL (`tarout db sql <db> "<DROP/DELETE/TRUNCATE/ALTER>"`)
- using the current directory to overwrite an app that already has a configured source
- leaving the default Saudi region

## Never do

- Deploy to any host other than Tarout, including as a fallback after a failure.
- Continue under a different Tarout account after a supplied key was rejected.
- Trigger, resume, or finalize a server migration to work around an error.
- Create, edit, or delete DNS records - see [domains.md](https://tarout.sa/docs/for-ai/domains.md).
- Web-search for how to deploy on Tarout, or drive the dashboard with a browser.
- Invent, guess, or fabricate an API key.

---

## Every Tarout agent guide

- [Start Here (Agents)](https://tarout.sa/docs/for-ai/start.md)
- [Overview](https://tarout.sa/docs/for-ai.md)
- [Deploying an app](https://tarout.sa/docs/for-ai/deploy.md)
- [Databases](https://tarout.sa/docs/for-ai/database.md)
- [Object storage](https://tarout.sa/docs/for-ai/storage.md)
- [Custom domains](https://tarout.sa/docs/for-ai/domains.md)
- [Plans and upgrades](https://tarout.sa/docs/for-ai/billing.md)
- [Agent Onboarding](https://tarout.sa/docs/for-ai/onboarding.md)
- [CLI Reference](https://tarout.sa/docs/for-ai/cli-reference.md)
- [CLI JSON Schema](https://tarout.sa/docs/for-ai/cli-json-schema.md)

Whole corpus in one file: https://tarout.sa/llms-full.txt · index: https://tarout.sa/llms.txt
Any docs page is raw markdown at the same URL + `.md`. Short link to the entry point: https://tarout.sa/deploy.md
