Skip to main content
Something not working? Here are the most common issues and how to fix them.

Common issues

Symptom: An agent fails its first message with an authentication error.Fix: Add the provider’s API key on Desktop’s AI Providers page — it’s saved to the encrypted credential store and picked up on the agent’s next message. Running the HQ standalone? Set the provider’s environment variable (e.g. ANTHROPIC_API_KEY) instead. See AI Providers.
Symptom: WebSocket connection to ws://localhost:9200/ws/chat is refused.Fix: Make sure the HQ is running. If using Desktop, check that the HQ process is healthy from the app. If running standalone, check the server logs for “HQ channel server listening on port 9200”.
Symptom: A Desktop or other loopback WebSocket connection closes immediately with code 4001.Fix: Include the desktop chat token as a query parameter: ws://localhost:9200/ws/chat?token=your-chat-token. This loopback compatibility path uses the chat token, not the administrative management bearer. Native apps use the Mobile bearer flow described below instead.
Error (via Chat API):
Fix: The message references a squad member that doesn’t exist. Open Desktop’s Squad page (or call GET /agents on the Management API) and make sure the name matches a deployed squad member.

Conversation sync and resumable chat

Symptom: A mutation returns HTTP 409 with conversation_busy, or chat returns an error frame with the same code. The error may include an activeTurnId.Fix: Refresh GET /mobile/v1/conversations/:id and use its activeTurnId. Replay from your last applied sequence, then either send resume for that same turn ID or send cancel for it. Wait until a terminal frame is durable and the refreshed summary no longer has an active turn before retrying the mutation or starting another turn. Do not work around the lease by sending the prompt again with a new ID; that can duplicate model work.If the error says The previous turn is still settling, the HQ is waiting for the previous provider run to finish. After cancellation, cleanup can continue even when the conversation summary no longer has an active turn. Wait briefly before retrying. Legacy chat also rejects a second response while the same conversation is running on another connection.
Symptom: Legacy chat returns No active legacy request for this connection. when you answer a question, steer a response, or send a Follow Up.Fix: Send the control on the connection that started the active request. A rejected message does not take ownership of a response running on another connection. Wait for that response to finish before starting a new request from this connection.
Symptom: The next durable WebSocket frame has a higher seq than expected, or a socket closed while a resumable turn was running.Fix: Keep the highest sequence you applied. Request GET /mobile/v1/agents/:agentId/conversations/:conversationId/events?sinceSeq=<last-seq> and apply the returned entries in ascending sequence order. If the same turn is still active, send this frame with the original turn ID:
Resume is idempotent. Do not resend the original message with a new turn ID.
Symptom: PATCH or DELETE returns HTTP 409 with revision_conflict after another client changed the conversation.Fix: Replace your cached conversation summary with the complete summary in details.current. Reapply the intended title or metadata change to that current value, then retry with its revision in a quoted If-Match header. Do not automatically retry a delete without first showing or checking the newer state.
Symptom: A management request returns HTTP 401, direct chat closes with WebSocket code 4001, or a relayed WebSocket closes with 4401.Fix: Both native routes use the same phone-scoped Mobile bearer. Send it in the Authorization header for both /mobile/v1 and /ws/chat; never put it in the URL. A hosted relay additionally requires x-dash-relay-credential, but that credential does not replace the Mobile bearer enforced by the HQ. Pair the phone again if either credential was revoked. Never paste tokens into logs or support messages.
Symptom: HTTP returns 429, a structured error reports rate_limited, or a relayed WebSocket closes with code 4429.Fix: Stop reconnecting or retrying in a tight loop. Honor the HTTP Retry-After header or the retry delay supplied by the relay, then reconnect once. If no delay is supplied, use exponential backoff with jitter and reset it after a stable connection. Preserve your last applied sequence so the eventual reconnect replays the gap instead of resending prompts.
Symptom: The relay returns HTTP 502, chat reports gateway_offline, or the phone can reach Dash but not the paired HQ.Fix: Bring the HQ machine online and make sure the Dash HQ is running, then let its outbound relay connection re-establish. Until health succeeds, show cached conversation history as read-only: do not queue metadata mutations, deletes, or prompts as though they were accepted. Once connected, refresh summaries and replay from the last sequence. Re-pair only if the device credential was actually revoked; an ordinary offline period does not require it.
Fix: Confirm that the saved HQ is reachable. Previously synced conversations stay visible from cache while the HQ is offline, but cached history intentionally blocks creating, sending, renaming, and deleting until that HQ reconnects.
Symptom: Dash for iOS shows Message saved for recovery, and that chat’s composer is unavailable.Fix: Open Needs Recovery from Conversations and copy the exact message text. Preview or share any readable attachments before discarding the item. If Dash could not read the saved attachment data, the text remains available but those attachments cannot be previewed or shared. If a newer draft exists, Dash keeps that draft separate and places the earlier message here so neither payload is overwritten. The chat remains read-only until you explicitly discard the recovery item. Do not clear the app’s data or reinstall it before preserving anything you need.
Fix: Another paired client owns the canonical active turn. Wait for it to finish, watch the shared stream in Desktop, or explicitly stop it. Sending a second turn, renaming, and deleting are blocked until the active turn ends.
Fix: This is intentional. These conversations were stored locally by an older Desktop version. No automatic upload exists, and reconnecting an HQ does not move them. They remain readable on that computer under On this Mac.
Fix: Desktop refreshed a revision conflict because another client changed the canonical conversation first. Review the current title and state, then retry your rename or delete.
Fix: The HQ returned a required contract shape this desktop version cannot decode. Update Desktop rather than clearing history. Your canonical conversation remains on the HQ.
Fix: Refresh the task and confirm its HQ is reachable. Desktop fetches linked sessions by their canonical ID, including sessions beyond the first conversation page. A deleted canonical conversation stays deleted, and Desktop will not create an empty replacement.

Secrets and credentials

After adding or changing a key on the AI Providers page, the agent still hits an auth error.Fix: The HQ reads credentials fresh on each message, so a new key takes effect on the agent’s next message — send another one. If it still fails, confirm the key is valid with the provider and that you selected the right provider for the model the agent uses.
Provider keys live encrypted in ~/.dash/gateway/credentials.enc, decrypted with the key in ~/.dash/gateway/secret.key.Fix: If you copy ~/.dash to another machine, copy both files together — credentials.enc can’t be decrypted without its secret.key. If secret.key is lost, delete credentials.enc and re-enter your keys on the AI Providers page.

Remote access (relay)

Symptom: The HQ picker on Dash for iOS shows:
Couldn’t reach your Dash account service. Check your connection and try again.
Fix: This means loading your enrolled HQs failed — the app never confuses this with “no HQs enrolled,” so seeing this message doesn’t mean your account is empty. Check the phone’s connection and tap Retry. If it persists, confirm the machine that hosts your Dash account service is reachable from the internet.
Symptom: The HQ picker on Dash for iOS shows:
No HQs linked to your account yet. Open Desktop → Settings → Devices → Remote access to enroll this machine.
Fix: Open Settings → Devices → Remote access in Desktop on the machine running your HQ, sign in with the same Dash account, and click Create HQ. Then tap Refresh on that same empty screen in the app — the new HQ appears without signing out or restarting. (Once the list has HQs in it, pull down on the list to refresh instead.)
Symptom: Tapping an HQ in the picker shows:
This HQ needs to be re-enrolled from Desktop before app access works.
Fix: This HQ’s Remote access setup on Desktop predates this app’s account sign-in support, so it never registered the app’s chat capability. Open Desktop on the machine that runs this HQ — it updates the HQ’s app access automatically on launch — then try the HQ again in Dash for iOS.
Symptom: Pair Device shows No usable LAN IPv4 address is available. Connect this Mac to the same network as the phone and try again. Or it shows Could not determine which LAN IPv4 address to use when the computer has several active network connections.Fix: Connect this Mac to a Wi-Fi or Ethernet network the phone can reach, then reopen Settings → Devices to request a fresh code. If several networks are connected, make the phone-reachable network the default route or disconnect the others. Dash will not guess an address or put a loopback-only address in a phone pairing code. If a shared local network is unavailable, configure Remote access and use its relay pairing code instead.
Symptom: Pair Device shows Switch to the local HQ before pairing a device while Desktop is connected to an HQ on another machine.Fix: Open Settings → General → HQ and click Use this computer. Wait for the HQ row to show This computer, then return to Settings → Devices and request a fresh pairing code. Desktop only generates phone pairing codes for the local HQ it can provision safely.
Symptom: Clicking Sign in to Dash on Settings → Devices → Remote access opens the browser but Desktop shows Sign-in failed.Fix: Finish signing in within the browser tab that opened — Desktop is waiting for it to hand control back. If you closed the tab, dismissed it, or it timed out, click Sign in to Dash again to start over. Make sure the machine running Desktop has internet access.
Symptom: You’re signed in, but Desktop asks you to select an organization before you can create an HQ.Fix: HQs are owned by an organization, not by you personally. On the Dash sign-in page, create or choose an organization, then return to Settings → Devices → Remote access and try again. If you belong to more than one organization, make sure you’re signed in to the one that should own this HQ.
Symptom: You don’t see Create HQ, or clicking it shows Could not enroll an HQ.Fix: Create HQ only appears once you’re signed in — if you see Sign in to Dash instead, sign in first. If it fails because the address you chose is taken, pick a different name (see “The address I want is already taken” below). Otherwise it’s usually a temporary network problem: wait a moment and try again. The HQ needs to be running for it to connect out.
Symptom: Your phone reached your agents through the relay for a while, then couldn’t connect anymore — typically after the machine was asleep or powered off for an extended period.Fix: Usually none needed — the HQ renews its own relay connection in the background and reconnects on its own, even after being offline for weeks. Just give it a moment after the machine wakes up. You do not need to re-create the HQ or re-pair your phone. If it still hasn’t recovered after a few minutes, confirm the machine running Dash is online, then open Settings → Devices → Remote access and check that you see HQ ready at with your address. The HQ must be running for it to reconnect.
Symptom: The Pair Device section on Settings → Devices — used by the Dash Android app — says it connects over your local network even though you want remote access.Fix: The QR code only switches to remote access after you’ve created an HQ. On Settings → Devices, confirm the Remote access section shows HQ ready at with an address, then check the Pair Device section above it — the code now carries your relay address.
Symptom: A phone or tablet that used to work remotely now can’t reach your agents.Fix: If that device was removed under Settings → Devices → Paired devices (by you or from another machine), its credential no longer works — this is expected. On Android, pair it again: open Settings → Devices, scan a fresh QR code on the phone, and it gets a new credential. On iOS, open Settings on the phone, choose Disconnect & Forget, then sign back in and tap the HQ again in the picker — no QR code needed.
Symptom: When creating an HQ, the address (hostname) you typed is rejected as unavailable.Fix: Relay addresses are globally unique and permanent — once a name is claimed it belongs to that HQ forever and is never released for reuse, even if the original HQ was later removed. Pick a different, more specific name (for example add your initials or your machine’s name) and try again. The availability indicator in the picker tells you live whether a name is free before you commit to it.
Symptom: Signing in on a new browser shows Approve this device with “Waiting for approval — scan this code with the Dash app on your phone.” and a QR code, then instead of continuing to chat it settles on one of:
Approval declined. You can try again from the HQ list.
The code expired. Try again from the HQ list.
Fix: This screen only appears on accounts that already have a Dash for iOS device signed in — new browser sessions need one of those devices to approve them. Approval declined means someone tapped Deny on the phone; The code expired means nobody approved it within the time limit. Either way, go back to the HQ list and sign in again to get a fresh code, then open Dash on the phone, go to Settings → Approve a device, and scan it before it expires.
Symptom: Scanning a browser’s approval code from Settings → Approve a device shows:
This code has expired. Ask the device to try again.
Fix: Approval codes expire a few minutes after they’re generated. Ask whoever is waiting on the browser to reload the HQ list (or sign in again) to get a fresh code, then scan the new one right away. A code that’s still valid instead shows a confirm sheet reading Allow "<device>" to access <HQ>? — tap Approve or Deny there.

Remote HQs

Symptom: You deployed or entered a remote HQ, but Desktop still shows agents from the local machine.Fix: Open Settings → General → HQ and check the active HQ status. If it says This computer, click Change HQ, choose Connect existing HQ, test the connection, then click Use this HQ. If you want to return to local mode, click Use this computer.
Symptom: Settings → General → HQ shows an existing HQ with an unhealthy status.Fix: Confirm the management URL is reachable, the management token is correct, and the relay credential is still valid. Click Change HQ and test the connection again before using it. For a VPS deployment, SSH to the server and run:
Symptom: Deploy and connect fails before the HQ is saved.Fix: Open Settings → General → HQ, click Change HQ, then choose Self-host on a VPS. Make sure the SSH host, user, port, and key are correct. The VPS must have git, node, npm, and systemctl --user available. If the relay URL or HQ id is wrong, fix those fields and deploy again.
Symptom: Desktop can list agents, but chat messages hang or fail.Fix: Open Settings → General → HQ, click Change HQ, choose Connect existing HQ, and test the connection again. The chat URL should use wss:// for HTTPS relays and point at the same HQ host as the management URL.

Tool errors

If a tool reports it can’t find files, check that the workspace path in your agent config exists. Dash creates the workspace directory automatically at startup, but if the config path is wrong, the tool may be looking in the wrong place.
Error:
The read tool blocks paths that resolve outside the workspace. This is intentional — use absolute paths or paths relative to the workspace root.
Error:
The bash tool has a 30-second timeout. Long-running commands are killed after this period. Break long operations into smaller steps or increase the timeout in the source code if needed.
The bash tool limits output to 100 KB. If a command produces more output, pipe it through head, tail, or redirect to a file and use read to retrieve specific sections.

Plugins

A plugin you installed isn’t showing its skills or commands.Fix: Open Desktop’s Plugins screen and check the plugin’s status badge. Disabled means it’s turned off — click Enable. Error means it failed to load — the card shows the failure message (usually a bad manifest or a missing SKILL.md). If hand-editing, make sure the plugin has an entry in ~/.dash/gateway/plugins/config.json with "enabled": true. See Plugins.
A plugin’s MCP servers, hooks, bin/ executables, or providers do nothing, even though the plugin is enabled.This is intentional. A freshly installed plugin is enabled but not trusted — its skills and commands work, but its code and credential components stay inert until you trust it. Click Trust on the plugin card, review the confirmation listing what will run, and confirm. See the Security model.
Typing /<plugin>:<command> doesn’t resolve.Fix: Commands are namespaced as /<plugin>:<command> — a plugin named research with commands/triage.md is /research:triage, not /triage. Confirm the plugin is enabled (commands need only enabled, not trust) and Loaded on the Plugins screen, and that the file lives in the plugin’s commands/ directory. See Invoking each component.
Open the model picker again after updating your HQ. The HQ refreshes its provider list on the first request after six hours, and sooner when its bundled catalog changes. Desktop’s refresh action can fetch it immediately.Dash curates models for chat and tool use. A newly released model may need a catalog update before it appears. Free/batch variants and unreviewed previews are not automatically included. Make sure you are viewing OpenRouter; a model under a direct provider is a separate entry.If OpenRouter is temporarily unavailable, Dash keeps the last successful list and retries when the picker is opened after five minutes.
A model from a plugin’s LLM provider doesn’t appear in the agent’s model picker.Fix: Plugin providers need two things: the plugin must be trusted (an untrusted plugin’s provider catalog is withheld entirely), and you must add an API key for it on the AI Providers screen. Trust the plugin, add the key, then the provider’s <id>/<model-id> models become selectable. See Provider credentials.
POST /plugins/install (or the Install button) returned an error.Fix: The response code tells you why. 404 — the source wasn’t found (a missing repo, dead URL, or unknown name); check the source string. 409 — a plugin with that name is already installed; remove it first or install under a different name. 422 — the plugin is invalid, corrupt, or the security scan flagged it as dangerous and refused it; inspect the source before retrying. See What the errors mean.
A plugin you removed still appears, or a hand-dropped plugin doesn’t show up.Fix: The HQ hot-reloads on changes made through Desktop or the management API, but it doesn’t watch the folder for files you add or delete by hand. After editing ~/.dash/gateway/plugins/ directly, trigger a rescan with POST /plugins/reload (or restart the HQ). Note that removing a plugin only deletes its directory when it was installed by the management API — a hand-dropped or path-linked plugin is left on disk by design.

Sub-agents

An agent tried to launch a sub-agent and got an error instead. In chat this appears as a red error tool block on the agent (or spawn_worker) call.This is a cap doing its job. The message tells you which one:
  • too many workers running at once (max N) — wait for workers to finish — the agent’s concurrent limit.
  • swarm run reached its worker limit (N workers per run) — the total-per-turn limit.
  • the HQ is at its global worker limit (N) — wait for workers to finish — the HQ-wide ceiling across all agents.
Raise the relevant cap in the agent’s subagents block if the work genuinely needs more — see Configuration → Sub-agents. The change takes effect on the agent’s next message. The HQ-wide ceiling (default 16) is raised by setting SUBAGENTS_MAX_CONCURRENT_GLOBAL where the HQ runs and restarting it — see Configuration → HQ defaults.
Error:
A sub-agent type asked for tools that its parent does not have, so the intersection came out empty — and Dash refuses to run a tool-less agent rather than launching one that can do nothing. The message names the entries that resolved to nothing.Fix: either give the parent agent those tools (Desktop → the agent’s Configuration tab → Tools, and its assigned MCP servers for mcp__… entries), or edit the type’s tools: frontmatter to ask for something the parent has. A sub-agent can never hold a tool or MCP server its parent lacks — see Configuration → Sub-agent types.
Error:
Sub-agents may nest, but only so far. A direct child is depth 1, and the ceiling is subagents.maxDepth (default 3).Fix: raise maxDepth for that agent, or have the work done one level up. Note that an agent already at the ceiling is not given the agent tool at all, so in most cases it simply won’t try. Separately, chat shows one level of nesting: expanding a sub-agent shows its transcript, and a row inside that transcript reads “Nested agents this deep are not opened here.” — that is the display limit, not the run limit.
Note on the tool result:
The agent tool’s model parameter accepts short alias names as well as full model ids. An alias is looked up in the agent’s subagents.modelAliases, and no aliases are configured by default — which model opus should mean depends on which provider the agent uses, so nothing is assumed. An alias that isn’t in the map resolves to nothing, the sub-agent runs on the parent’s model, and the note above is appended to the tool result. Nothing failed.Fix: add the alias to the agent’s subagents.modelAliases (for example {"opus": "anthropic/claude-opus-4-6"}), or pass a full provider/model id (or inherit) instead. Either way, if the id isn’t the parent’s model or one of its fallbacks, add it to the agent’s subagents.allowedModels first — see Configuration → Sub-agents.
A sub-agent asked a question with ask_orchestrator, showed as waiting for input, and then carried on — or finished — without anyone answering. Its own transcript shows the call coming back as ask_orchestrator aborted.A question lives only as long as the turn that launched the sub-agent. When that turn ends, any question still open is dropped so the sub-agent is not left waiting on a conversation that has moved on. A foreground sub-agent holds its parent’s turn open until it finishes, so there is time to answer from the reply box on its row. A background sub-agent usually outlives the turn that launched it, so a question it asks after that turn has ended has nobody to answer it.Fix: answer while the turn is still running, or launch the sub-agent in the foreground when you expect it to need a decision. A brief that tells the sub-agent what to assume when it cannot ask is the sturdier fix for background work.
Error:
isolation: worktree gives a sub-agent its own checkout of the workspace, cut from whatever commit the workspace is on right now. That needs the workspace to be inside a git repository.Fix: run git init in the agent’s working directory (or point the agent at a directory that is already a repo), or drop isolation and let the sub-agent share the parent’s workspace.
A directory is still sitting under ~/.dash/gateway/worktrees/<agent-name>/<subagent-id>/ after the sub-agent finished.This is by design when the worktree holds work. Cleanup removes a worktree only when there is nothing to lose: uncommitted changes, untracked files, and commits that no branch or tag would keep alive all keep it. (Regenerable litter — node_modules/, dist/, build/, .next/, coverage/, *.log, .DS_Store — does not count.) The path is not handed back to you in the chat: to find it, either fill in the template above with the sub-agent’s id, or look in the HQ log, where every kept worktree is recorded with a line containing keeping and the path, and why it was kept.Fix: look at what’s inside and keep or merge what you want. Once the checkout is clean, git worktree remove <path> from the parent repository takes it down; git refuses while there are changes in it, so commit or discard them first (or pass --force if you are sure).
The HQ process died (crash, force-quit, machine reboot) while sub-agents were still working.Recovery is automatic. On its next start the HQ marks every sub-agent that was still running as interrupted, keeps its transcript, and tells its parent agent — as a notification turn delivered as soon as the HQ is serving again (or with the parent’s next turn, if it’s busy). The rows stop spinning and show interrupted.Unlike earlier releases, an interrupted sub-agent is not lost: press Resume on its row — from the web tasks panel, the iOS tasks sheet, or POST /subagents/:id/resume; Desktop greys the button once a sub-agent is terminal — or have the parent send_message it, and it picks up with its context intact. Orphaned worktrees are swept at the same time, except ones holding work.
A Resume — from a row, from the tasks list, or from the parent’s own send_message — comes back with an error instead. There are three common reasons, and a resume also counts against the launch caps, so the two cap messages described under “A sub-agent didn’t start (cap reached)” above can arrive here too:
  • Agent "..." is a one-shot Explore agent and cannot be resumed.Explore and Plan are read-only, one-shot types, so they cannot be given a new task. Fix: launch a new one with the follow-up task. (If the agent is still running and asking a question, that is an answer, not a resume, and it goes through: the parent’s send_message, the reply box on its row and the legacy send_to_worker all reach a paused one-shot.)
  • steer cap reached for "..." (max 10 per agent). — you’ve hit the per-child message cap, which counts across resumes for as long as the HQ holds that child in memory (a restart resets it to zero). Fix: raise swarm.maxSteersPerWorker for the agent, or start a fresh sub-agent.
  • Agent "..." cannot be resumed: its grant cannot be rebuilt. — the parent’s grant could not be re-established. Either sub-agents have been turned off on the parent agent (or the agent itself was deleted — its conversations survive the delete, but nothing under them can run again), or the parent conversation (or one above it) was deleted — deleting a conversation stops everything under it from running again. A sub-agent created by an older HQ build, before the grant was stored beside the row, has the same symptom. Fix: re-enable sub-agents on the parent agent — see Configuration → Per-agent settings. A deleted parent, a deleted agent and a grant that was never stored cannot be recovered, so launch a new sub-agent instead.
A resume also silently re-intersects the child’s tools and MCP servers with what its parent holds now, so a resumed sub-agent can come back with fewer tools than it had, without any message saying so. Its model is not re-checked: a child keeps the model it was launched with even if that model has since been removed from the parent’s allowed set.Desktop’s panel also greys Resume out for a sub-agent that has already finished; use the web tasks panel or POST /subagents/:id/resume to resume one from there.
A sub-agent is a conversation of its own, so its transcript is where every other conversation is:
Read it in the app instead: expand the sub-agent’s row in chat, or open it from the tasks panel. Transcripts are never auto-deleted. Older releases wrote workers under ~/.dash/gateway/sessions/<agent-name>/.swarm/<runId>/; those directories are no longer written to and are left alone — remove them by hand if you want the space.
You chat with an agent over a messaging app and see only the final answer — no per-sub-agent updates.This is by design. Sub-agent rows, the tasks panel and sheet, and Desktop’s Sub-agents panel are chat-app features (iOS, the web client, and Desktop). Messaging channels deliver only the agent’s final response, not the intermediate sub-agent events. To watch and steer sub-agents in real time, chat with the agent in one of those clients.
Conversations recorded before this release replay fine — each worker still draws exactly one card, in the same place, with the same status. One narrow case loses detail: a worker that was cancelled after its viewer had already gone away recorded its reason only on an event type that no longer exists, so its card now settles on cancelled without the explanatory note. Nothing else about the replay changed, and nothing needs fixing.

Session issues

Provider session JSONL stores the model’s working context separately from the canonical conversation that Desktop and paired phones display. If a provider session file has an invalid line after a crash, the agent may fail to restore model context even though canonical history remains visible. To recover:
  1. Find the conversation’s session directory: ~/.dash/gateway/sessions/{agent-name}/{conversationId}/ and open the .jsonl session file inside it
  2. Open it in a text editor
  3. Remove or fix the malformed line(s) — each line should be a valid JSON object
  4. Restart Dash
Since provider session JSONL is append-only, you can remove malformed lines from the end without damaging earlier model context. This does not edit the canonical rendered messages.
To reset only the agent’s provider session state, delete its session directory:
To reset all provider session state:
These commands do not delete canonical conversations shown by Desktop or paired phone apps. To remove shared history, reconnect the HQ and delete the conversation in Dash.
Dash now keeps everything under ~/.dash (HQ data, desktop app data, logs, and agent workspaces). The first time a newer version starts, it automatically moves data from the old locations into ~/.dash — your credentials, agents, and conversations come along.If something looks missing, check the old locations:
  • macOS: ~/Library/Application Support/dash and ~/Library/Application Support/dash-gateway
  • Linux: ~/.local/share/dash and ~/.local/share/dash-gateway
  • Agent workspaces: the old ~/dash-workspaces
The migration only runs when ~/.dash doesn’t already have that data, and it never deletes the originals — so it’s always safe to copy anything left behind by hand. To pin Dash to a specific location instead, set DASH_HOME.

Docker issues

Dash stores everything under DASH_HOME (set to /data in the container). Make sure that path is backed by a persistent volume in docker-compose.yml:
Without this volume, credentials, agents, and sessions live only inside the container and are lost when it’s recreated.

Debug logging

Desktop and the HQ write logs to ~/.dash/logs/ (mc.log and gateway.log) — check there first when something goes wrong. For a standalone HQ, add the --verbose flag to get debug-level output: