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

# Docker Troubleshooting

> Common failure modes and how to diagnose them

## Startup failures

### `[SYS-REPLAY-001] REDIS_URL is required`

The server will not start without Redis. This error means `REDIS_URL` is either not set, or the Redis service is not reachable when the server starts.

**Diagnose:**

```bash theme={null}
docker compose ps                                    # is redis running?
docker compose logs redis --tail=20                  # did redis start cleanly?
docker compose exec server env | grep REDIS_URL      # is the variable set?
```

**Fix:** Ensure the `redis` service is in the compose file, `REDIS_URL` is set to `redis://redis:6379`, and the server's `depends_on` includes `redis`.

***

### `Parmana server must be started from repository root. Missing: /app/policies`

The server checks for required files at startup. If `policies/`, `trust/root.pub`, `trust/trust-root.json`, or `artifacts/release-manifest.json` are missing inside the container, it exits immediately.

**Diagnose:**

```bash theme={null}
docker compose exec server ls /app/policies
docker compose exec server ls /app/trust
docker compose exec server ls /app/artifacts
```

**Fix:** These files must be present in the Docker image at build time, or mounted via volumes. If using a pre-built image, verify the image version matches your policy bundle layout.

***

### Server exits immediately with no log output

The process may be crashing before Fastify initializes logging. Run the container interactively:

```bash theme={null}
docker compose run --rm server
```

***

### `[SYS-KEY-001]` or signing key error on startup

The signing key could not be loaded. Check the provider configuration:

```bash theme={null}
docker compose exec server env | grep PARMANA_SIGNING
```

* If `PARMANA_SIGNING_PROVIDER=disk`: verify the key file exists at `PARMANA_SIGNING_PRIVATE_KEY_PATH` inside the container, and that the host volume is mounted correctly.
* If `PARMANA_SIGNING_PROVIDER=env`: verify `PARMANA_SIGNING_PRIVATE_KEY` is set and contains a valid PEM-encoded Ed25519 private key (including `-----BEGIN PRIVATE KEY-----` header).

***

## Request failures

### `POST /execute` returns 401 Unauthorized

The `Authorization: Bearer <token>` header is missing or the token does not match `PARMANA_API_KEY`.

```bash theme={null}
curl -X POST http://localhost:3000/execute \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

***

### `POST /execute` returns 422 with "Policy not found" or "Failed to load bundle"

The policy bundle does not exist at the expected path inside the container.

**Expected path:** `$PARMANA_POLICIES_ROOT/{policyId}/{policyVersion}/`

**Required files in the bundle directory:**

* `policy.json`
* `bundle.manifest.json`
* `bundle.sig`

**Diagnose:**

```bash theme={null}
docker compose exec server \
  ls /app/policies/claims-approval/1.0.0/
```

**Fix:** Build or copy the compiled bundle into the container. Compile and sign policies before building the image.

***

### `POST /execute` returns 503 with "Governed execution runtime not configured"

The `signer`, `verifier`, or `replayStore` is not configured. Check:

```bash theme={null}
curl http://localhost:3000/health | jq .
```

Look at `verification`. If it is not `"ok"`, the signing key is misconfigured.

***

### `POST /execute` returns 422 with `[INV-013@replay] Replay detected`

An execution with the same `executionId` has already been processed. Each business transaction must use a unique `executionId`.

This is expected behavior — the replay store is working. If you need to re-run a test, use a different `executionId`.

***

### `POST /execute` returns 413 Request Entity Too Large

The request body exceeds 64 KB (65,536 bytes). The `signals` object is too large.

Reduce the size of the signals payload. Signals should contain decision-relevant structured data, not raw documents or binary data.

***

### `POST /override` returns 404 "Pending override not found"

The `executionId` does not have a pending override in the audit database. Possible causes:

* The execution did not produce `execution_state: "pending_override"`
* The override was already resolved
* The audit database is not connected (`audit_db: false` in `/health`)

***

## Database issues

### Audit records not appearing in dashboard

Verify Postgres is connected:

```bash theme={null}
curl http://localhost:3000/health | jq '.audit_db'
```

If `false`, check the Postgres container and `AUDIT_DATABASE_URL`.

***

### Postgres fails with "database does not exist"

The `POSTGRES_DB` environment variable must match the database name in `AUDIT_DATABASE_URL`. Default is `Parmana_audit`.

If the volume was initialized with a different database name, remove the volume and restart:

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

***

### Postgres fails with "password authentication failed"

`POSTGRES_PASSWORD` in `.env` does not match the password stored in the volume. The volume retains the password from when it was first created. Options:

* Use the original password, or
* Remove the volume and restart (this deletes all audit data)

***

## Network issues

### Dashboard shows "Cannot connect to server"

The dashboard makes API calls from the browser to `http://localhost:3000`. Ensure:

* The server is accessible on your machine at port 3000
* `CORS_ORIGIN` on the server is set to `http://localhost:8081`
* No browser extension is blocking the request

***

### Services cannot communicate (container-to-container)

All services must be on the same Docker network (`parmana-net`). Verify each service has `networks: - parmana-net`:

```bash theme={null}
docker network inspect parmana_parmana-net
```

***

## Log reference

```bash theme={null}
# Tail server logs
docker compose logs server -f

# Tail all services
docker compose logs -f

# Last 100 lines from postgres
docker compose logs postgres --tail=100

# Parse JSON log output (server uses structured JSON logging)
docker compose logs server -f | jq .
```

Server log fields of interest:

| Field      | Description                                       |
| ---------- | ------------------------------------------------- |
| `level`    | Log level: `info`, `warn`, `error`                |
| `msg`      | Event — e.g. `execute:success`, `execute:failure` |
| `reqId`    | Per-request ID for correlation                    |
| `policyId` | Policy used in the execution                      |
| `error`    | Error message if execution failed                 |
