> ## Documentation Index
> Fetch the complete documentation index at: https://docs.shipvoice.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting

> The quiet failures in this stack, what each one looks like, and the fix.

Every failure here is quiet. A mismatched agent name mints a valid token, opens
a real room, connects the browser, and logs no error anywhere. So read this page
before you read logs.

## Run the doctor first

```bash theme={null}
cd agent
uv run python ../scripts/doctor.py --live
```

One line per check, with the fix underneath. Without `--live` it reads
configuration only. With `--live` it also probes the three provider APIs, asks
`docker compose ps` whether all four services are running, hits the backend's
`/health`, mints a real token, and reads `/api/v1/agents`.

Two things about how it reads config:

* It runs through the agent's environment because it imports `httpx`. Hence
  `cd agent` and the `../` in the path.
* It parses the **root** `.env` only. A key that lives in `agent/.env` and
  nowhere else is invisible to it, and it reports that key as unset.

## The room opens and nothing ever speaks

`AGENT_NAME` and `VITE_AGENT_NAME` differ. LiveKit dispatches the worker by
exact string match, so when the two differ the token is valid, the room is real,
the browser connects, and no worker is ever dispatched. Nothing errors. The
doctor checks this before anything else for that reason.

```bash theme={null}
AGENT_NAME=assistant
VITE_AGENT_NAME=assistant
```

Byte-identical, in the root `.env`. Change both or neither.

## You changed a `VITE_` value and nothing changed

`VITE_TOKEN_ENDPOINT`, `VITE_AGENT_NAME` and `VITE_API_BASE_URL` are build
arguments in `docker-compose.yml`, baked into the frontend bundle when the image
is built.

```bash theme={null}
docker compose up -d --build
```

A plain `docker compose restart` keeps the old value silently, which is one of
the ways you end up with a mismatched agent name.

## Compose works but the manual run does not, or the reverse

You edited the wrong `.env`. `docker compose` reads the root one and nothing
else. The per-service files (`agent/.env`, `backend/.env`, `frontend/.env`) are
for running that service by hand.

## The browser says "invalid API key"

`LIVEKIT_URL` is unset or is still `wss://your-project.livekit.cloud`. The
message points at the key, but the URL is the problem. The doctor names this
case explicitly so you do not rotate a key that was never wrong.

## Saving the prompt in the console is refused

The status code tells the two refusals apart.

* **403.** `CONSOLE_WRITES_ENABLED` is off. It defaults to `false` in code and
  compose sets it to `true`. The editor loads read-only and says why.
* **409.** The backend has no read-write mount of `./agent/prompts`, so the save
  cannot land. The message names the path it could not write, and the prompt the
  agent is running is unchanged.

See [Customize](/customize).

## Console edits to the LiveKit project do not reach the worker

The worker takes its LiveKit project from the backend when `BACKEND_API_URL` and
`BACKEND_API_TOKEN` are both set, and restarts itself when the stored project
changes. Two failures:

* `AGENT_SERVICE_TOKEN` and `BACKEND_API_TOKEN` differ. They are one secret with
  two names. The backend answers 403 and the worker logs that it was refused.
* Both are empty. The endpoint that serves the credentials is disabled rather
  than opened, and the worker stays on its own environment.

Generate one value and put it in both:

```bash theme={null}
openssl rand -hex 32
```

## The Calls page is empty after a real call

Call reporting needs `BACKEND_REPORTING_ENABLED=true` and the matching service
token above. Compose turns reporting on by default, but without the token pair
nothing is sent. Console mode never reports, whatever the flag says.

## The worker exits immediately and names a LiveKit value

It needs all three of `LIVEKIT_URL`, `LIVEKIT_API_KEY` and
`LIVEKIT_API_SECRET`. Rather than looping raw 401s under
`restart: unless-stopped`, it refuses to start and says which one is missing.
The doctor reports each of the three separately.

```bash theme={null}
docker compose logs agent
```
