# Troubleshooting

<Callout type="tip">
  You can ask OpenCode to debug itself. Describe the problem and ask it to use this troubleshooting page; it can read
  the steps below, inspect its service and logs, and help identify the issue.
</Callout>

OpenCode uses a client-server architecture. A background server owns sessions, plugins, permissions, and other application
state. Start by determining whether an issue is in a client, the shared server, or a specific project.

## Check the background service

Show the current server information:

```bash
opencode service status
```

Verify that its API is healthy:

```bash
opencode api get /api/info
```

If the service is stuck or unhealthy, restart it:

```bash
opencode service restart
```

You can also stop and start it explicitly:

```bash
opencode service stop
opencode service start
```

<Callout type="note">
  OpenCode normally discovers or starts the shared background service automatically. The service commands are only
  needed when diagnosing its lifecycle.
</Callout>

## Allow a browser origin

If a browser client on another origin cannot connect because of CORS, add the client's origin to the service configuration:

```bash
opencode service set cors http://192.168.1.10:3001
opencode service get cors
```

Use an exact HTTP or HTTPS origin, including the port when needed, without a path or trailing slash. To allow multiple
origins, pass a comma-separated list as one argument; whitespace around each origin is trimmed:

```bash
opencode service set cors "http://192.168.1.10:3001, https://app.example.com"
```

`service get cors` prints a JSON array. Remove the configured list with:

```bash
opencode service unset cors
```

Setting or unsetting service configuration stops the background service. Its next start picks up the new configuration;
use `opencode service start` to start it explicitly.

For a foreground server, repeat `--cors` for each additional allowed origin:

```bash
opencode serve --cors http://192.168.1.10:3001 --cors https://app.example.com
```

With `serve --service`, supplied `--cors` flags override the persisted list for that process. Without those flags, service
mode uses the persisted list. CORS does not change the listening address or bypass server authentication.

## Inspect the API

The `api` command uses the local service discovery and authentication flow. It accepts either an HTTP method and path or an
OpenAPI operation ID.

See the [API reference](/api) for all endpoints and operation IDs.

Pass a JSON request body with `--data` or `-d`, and add headers with `--header` or `-H`.

<Callout type="warning">
  Running `opencode api` may start the background service when no compatible healthy service is available.
</Callout>

## Read logs

Installed builds write logs to:

```text
~/.local/share/opencode/log/opencode.log
```

Follow the log while reproducing the problem:

```bash
tail -f ~/.local/share/opencode/log/opencode.log
```

Each line includes a process `run` ID and a `role` field. Use `role=server` for session, provider, plugin, permission, and
tool activity.

```bash
grep 'role=server' ~/.local/share/opencode/log/opencode.log
grep 'run=8fc3b1d5' ~/.local/share/opencode/log/opencode.log
```

## Capture a heap snapshot

Write a memory (heap) snapshot of the running background server on any platform:

```bash
opencode debug heap-dump
```

The command waits until the snapshot is complete, then prints its path:

```text
/home/me/.local/share/opencode/log/heap-48213-2026-10-23T013012345Z.heapsnapshot
```

Write it somewhere else with `--directory`. The server creates the directory when it is missing:

```bash
opencode debug heap-dump --directory ./snapshots
```

- It only uses a server that is already running. It never starts, replaces, or restarts one.
- Use `--server <url>` to capture a server you started with `opencode serve`. Set `OPENCODE_PASSWORD` if it has one.
  `--directory` is then a path on the server's machine.
- Open the file in the Memory panel of Chrome DevTools.

<Callout type="warning">
  The server pauses while it writes the snapshot, and its memory use can increase for a short time. The snapshot can
  contain prompts, file contents, and credentials. Do not share it publicly.
</Callout>

### In the desktop app

Run **Capture heap snapshots** from the command palette. It writes one folder in your Downloads folder with a snapshot of
each part of the app, plus a breakdown of the memory a snapshot cannot show:

```text
opencode-heap-2026-10-23T013012345Z/
  memory.json                  where the memory is, per process, in MiB: start here
  memory-infra.json            Chromium's memory dump trace; open it in https://ui.perfetto.dev
  heap-48213-….heapsnapshot    the desktop's own server
  window-1-48390.heapsnapshot  one per app window
  main-48102.heapsnapshot      the desktop main process
  gpu.json                     the GPU and driver
  manifest.json                processes, PIDs, and memory before and after; written last
```

- A heap snapshot holds only JavaScript objects and the page. Images, layout, compositor layers and GPU memory are in
  `memory.json` and `memory-infra.json` instead.
- Remote servers are not captured. Use `opencode debug heap-dump` on that machine instead.
- The server writes its snapshot straight into the folder, so nothing large is moved or copied.
- Browser tabs are not included, because their snapshots contain the content of the pages you visited.

## Capture CPU and memory profiles

On macOS and Linux, you can signal a running OpenCode process to capture diagnostic data. Get the background server PID
from the health endpoint:

```bash
opencode api get /api/info
```

Use the `pid` from the response with one of these signals:

- `SIGPROF` captures a ten-second CPU profile:

  ```bash
  kill -SIGPROF <pid>
  ```

  The result is written to the log directory as `cpu-<pid>-<timestamp>.cpuprofile`.

- `SIGUSR1` captures a memory (heap) snapshot:

  ```bash
  kill -SIGUSR1 <pid>
  ```

  The result is written to the log directory as `heap-<pid>-<timestamp>.heapsnapshot`.

Wait for `CPU profile written` or `heap snapshot written` in `opencode.log` before opening the file. The corresponding
log entry includes its complete path. You can inspect both file types in Chrome DevTools.

<Callout type="note">
  Signal-triggered profiles are not available on Windows. Use `opencode debug heap-dump` for heap snapshots instead.
  Writing a heap snapshot can pause the process and temporarily increase its memory usage.
</Callout>

## Service files

The shared server registers itself at:

```text
~/.local/state/opencode/service.json
```

Its private service configuration is stored separately at:

```text
~/.config/opencode/service.json
```

The database normally lives at:

```text
~/.local/share/opencode/opencode.db
```

`OPENCODE_DB` can override the database location.

<Callout type="warning">
  Do not delete or edit service files or the database while troubleshooting. Use the service commands to manage the
  daemon, and make a backup before inspecting persistent data with external tools.
</Callout>

## Report an issue

Include the following when reporting a reproducible problem:

- Output from `opencode --version`
- Output from `opencode service status`
- The smallest sequence of steps that reproduces the issue
- Whether the issue affects the shared service, a specific client, or one project
- Relevant log lines, including their `run` and `role` fields

Remove API keys, authorization headers, prompts, file contents, and other sensitive data before sharing logs.

File reproducible problems in [GitHub Issues](https://github.com/anomalyco/opencode/issues).