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

# Troubleshooting

> What the common error states mean and how to recover.

This page maps observable symptoms (log lines, UI states) to fixes.

## "Another runner is already running - exiting"

**What it means.** The singleton lock at `~/.slackhive/runner.lock` is held by a live process. A second runner (from `npm run dev`, `tsx watch`, or an accidental re-invocation) tried to boot and refused.

**Fix:**

```bash theme={null}
slackhive stop
slackhive start
```

`slackhive stop` sweeps orphan processes and unlinks the lock. Then `start` acquires it cleanly.

## Amber "stale" dot on an agent

**What it means.** The agent's row says it's running, but the runner stopped sending heartbeats (missed ≥ 45s). Usually the runner crashed or was `kill -9`'d.

**Fix:**

```bash theme={null}
slackhive stop
slackhive start
```

Heartbeats resume within 15s of the new runner starting. The dot goes back to green.

## "Slack bot token is invalid or revoked"

**What it means.** The runner probed Slack with the saved bot token and Slack rejected it. The agent's `lastError` shows the full message.

**Fix:**

1. Open the affected agent → **Overview**
2. Open **Manage Slack** in the Slack connection card
3. Paste a fresh **Bot Token** and **App-Level Token**
4. Add the **Signing Secret** only if your workspace requires it
5. Save the connection, then restart the agent if it does not reconnect automatically

Token sources: [api.slack.com/apps](https://api.slack.com/apps) → OAuth & Permissions (bot token), Basic Information → App-Level Tokens (app token), Basic Information → Signing Secret.

## Stale lock after a crash

**What it means.** The runner was killed without cleanup (`kill -9`, power loss). The lock file points to a PID that no longer exists.

**Fix:** none needed - `slackhive start` auto-detects stale locks (checks the PID with `process.kill(pid, 0)`), removes the lock, and starts cleanly.

## Dashboard AI backend badge is amber or red

**What it means.** The dashboard header shows the active AI backend status. Amber usually means the local login or cached credential needs refresh. Red means SlackHive cannot find a usable credential for the selected backend.

**Fix:**

1. Open **Settings → AI Backend**
2. Check which backend is selected
3. For **Codex/OpenAI**, refresh your `codex login` / ChatGPT session or set `OPENAI_API_KEY`
4. For **Claude/Anthropic**, run `claude login` or set `ANTHROPIC_API_KEY`
5. Save or detect credentials again, then restart with `slackhive stop && slackhive start` if you changed `.env`

## OAuth MCP stopped working

**What it means.** The OAuth token expired or was revoked.

**Fix:**

1. Open **MCP Catalog**
2. Find the server and click **Test**
3. If the token is expired, click **Reconnect** or edit the server and paste a fresh token
4. If the server was imported from Claude Code CLI, refresh `claude login`, then re-import or update the server
5. If it references `${env:NAME}`, confirm the secret still exists in **Settings → Env Vars**

See [OAuth MCPs](/configuration/mcp-oauth).

## Linux: `claude login` says "keyring unavailable"

**What it means.** Common on headless servers or fresh Linux VMs - no GNOME/KDE keyring daemon running, so `secret-tool` has nowhere to write.

**Fix (pick one):**

* Start a lightweight keyring: `gnome-keyring-daemon --start` (requires dbus session)
* Set `DBUS_SESSION_BUS_ADDRESS` to an active bus if you have one
* Ignore it - `claude login` falls back to writing `~/.claude/.credentials.json` directly. SlackHive picks it up from there

The credentials file path is the reliable cross-platform source; keyring is just a convenience on desktop Linux.

## Port conflicts

**What it means.** Default ports 3001 (web) or 3002 (runner) are taken.

**Fix:** none - the CLI auto-negotiates free ports. Check the actual ports with:

```bash theme={null}
slackhive status
```

To pin specific ports, set `PORT` and `RUNNER_INTERNAL_PORT` in `.env`.

## Agent shows "error" status

**What it means.** The runner tried to start the agent and something failed - Slack auth, MCP connection, missing integration. The real reason is in `lastError` on the agent detail page.

**Fix:** read the error, fix the underlying cause (bad token, missing env var, offline MCP server), then restart the agent from the detail page.

## Logs don't show up in the UI

**What it means.** The log SSE stream is disconnected.

**Fix:** reload the page. If it stays disconnected, check `slackhive status` - the web server may be down. `slackhive start` recovers it.

## Agent directory left behind after delete

**What it means.** In older versions, deleting an agent left `~/.slackhive/agents/<slug>/` on disk. Fixed in the current release - delete now removes the directory too.

**Fix for legacy orphans:**

```bash theme={null}
# Compare DB to disk
sqlite3 ~/.slackhive/data.db "SELECT slug FROM agents;"
ls ~/.slackhive/agents/

# Remove directories that don't match any slug
rm -rf ~/.slackhive/agents/<orphan-slug>
```

## Still stuck?

Check `~/.slackhive/logs/runner.log` for the full stream. Each line is JSON - most errors include a `message` and an `error` field that points straight at the cause.
