DeepSeek Harness Plugin Troubleshooting: Install Errors, Patch Conflicts, Version Rollback & Profiles (2026)

Step-by-step fixes for DeepSeek Harness (dsh) plugin errors: pnpm allowlist failures, patch override order, profiles that do not apply, and version rollback.

Last updated: 2026-10-09

When to use this page

Use this page when something between "I found a plugin" and "the plugin is running" has gone wrong: a failed dsh plugin add, an odd pnpm-workspace allowlist failure in a monorepo, a cordis.patch.yml that ignores you, or a profile that loads the wrong plugin set. Each section below follows the same shape — symptom, then cause, then the commands that fix it.

If you have not reached the install step yet, start with Installing Plugins Safely. If you are not sure which config layer you are editing, read the Configuration Guide first.

One rule before everything else: restart dsh after every config change. The plugin tree is assembled at startup by the Cordis container, so half of all "nothing happened" tickets are config edits that were never restarted.

1. Plugin not found during install

Symptom. dsh plugin add dsh-some-tool fails with a resolution error, or succeeds but the plugin never appears anywhere.

Cause. The CLI resolves packages from the npm registry by exact name. The usual culprits: a typo in the package name, a missing @scope/ prefix, a plugin that is only distributed through GitHub (so it has no npm entry), and a --profile <name> flag that does not match the profile you start later — the entry lands in a profile you never launch.

Fix.

  1. Verify the exact published name: npm view dsh-some-tool. The plugin's detail page and repository README show the working install command — community installs are documented by the plugin itself.
  2. If the plugin is GitHub-only, install from source with a branch or tag pin: dsh plugin add github:owner/repo#main.
  3. Match the flag to the launch: if you installed with dsh plugin --profile web add <package>, start it with dsh --profile web — not a bare dsh.
  4. During local development, link the folder directly: dsh plugin add ./path/to/my-dsh-plugin.

2. Install hangs or fails: pnpm workspace allowlist

Symptom. Inside a pnpm monorepo, installing a plugin hangs, or fails with an error mentioning pnpm-workspace allowlist, module not found, or ESM & CJS resolution problems — especially when the plugin comes from a git or local build.

Cause. pnpm enforces strict dependency boundaries. A plugin installed from GitHub effectively becomes part of the workspace, and if its package is not declared within the workspace boundary, pnpm will not link it — so Node cannot resolve the plugin or its dependencies at runtime.

Fix.

  1. Declare the package inside the boundary: add it to the workspace root package.json dependencies (or the allowlist/catalog in pnpm-workspace.yaml), then run pnpm install from the workspace root.
  2. Re-add the plugin and restart: dsh plugin add <package>, then start dsh again so the rebuilt tree loads.
  3. Prefer the npm registry version when one exists — published packages carry their dependencies with them and skip the boundary problem entirely.
  4. Confirm the runtime: node -v should report 20.0.0 or higher.

Still stuck? The 2026 install-stuck receipts (#9178, #9261)

Two newer shapes from the official discussions, both matching the dsh 安装卡住 / install stuck search:

  1. dsh plugin add hangs on Windows and never exits (#9261). The command sits without returning and the profile's bundles never reconcile. Re-run the add command — a transient network stall is the usual trigger — and check the network route to the registry, switching to a mirror when the direct route is slow.
  2. A plugin silently installs an older version, then is judged incompatible (#9178). With pnpm 11, minimumReleaseAge defaults to 24 hours: a version published today is invisible to the resolver, so the install quietly degrades to an older release — which can then fail compatibility checks. Install an explicit package@version, or adjust minimumReleaseAge if you deliberately want same-day releases.

3. cordis.patch.yml conflicts (override order)

Symptom. Two plugins overlap — two sidebar panels, two OCR engines, two implementations of the same service — and one plugin's settings are silently ignored. dsh may report a Profile patch collision / Override order issue.

Cause. Patches are the top override layer above bundles and profiles, and later entries win. When two entries register the same service or UI panel, declaration order decides. A duplicated key or an indentation slip in the YAML can also silently rewrite an entry.

Fix.

  1. Open the file you actually use: cat ~/.dsh/profiles/<name>/cordis.patch.yml, or <project-root>/.dsh/cordis.patch.yml when you are inside a workspace.
  2. Reorder: move the plugin that should win to the bottom of the plugins: list — it overrides earlier entries.
  3. Or keep both but disarm the conflict: set enabled: false on one plugin's entry.
  4. Cleanest long-term fix: move the conflicting plugins into separate profiles and launch with dsh --profile <name>.
  5. Validate the YAML before restarting — one bad indent changes what an entry means: yq eval . cordis.patch.yml.

4. dsh bundle format errors

Symptom. dsh starts, but the plugin set looks nothing like the documentation, or a config file copied from somewhere keeps triggering collision errors instead of loading.

Cause. The three config layers have different jobs: a bundle is an official plugin set shipped with the harness, a profile is your named assembly of bundles and plugins, and a patch surgically overrides a single plugin entry. A cordis.patch.yml that re-declares an entire bundle — dozens of entries, plus settings that belong in the profile layer — mixes formats, and those overrides start colliding with what the bundle already provides.

Fix.

  1. Keep patches surgical — one plugin per entry, enabled and options only:
# ~/.dsh/profiles/default/cordis.patch.yml
plugins:
  dsh-vision-toolkit:
    enabled: true
    options:
      ocrEngine: 'default'
  1. If you want a whole set of plugins at once, configure the set at the profile level instead of pasting every entry into a patch.
  2. Delete the duplicated entries, save, and restart dsh. The plugin's tools or panels should now load with no collision messages.

5. Profile not taking effect

Symptom. You edited a cordis.patch.yml, restarted, and nothing changed — or a plugin you installed for a specific profile is nowhere to be found.

Cause. One of three classic mistakes: editing the wrong file (there are two locations, and the workspace file overrides the global one), launching with a different profile name than the folder you edited, or never restarting at all.

Fix.

  1. Check both locations: ls ~/.dsh/profiles/*/cordis.patch.yml 2>/dev/null and ls .dsh/cordis.patch.yml 2>/dev/null from the project root.
  2. Remember precedence: <project-root>/.dsh/cordis.patch.yml wins over ~/.dsh/profiles/<name>/cordis.patch.yml when both exist.
  3. Match the flag to the folder: editing ~/.dsh/profiles/web/cordis.patch.yml means launching with dsh --profile web — not dsh, and not dsh --profile headless.
  4. Restart and verify: dsh --profile web, then check that the plugin's tools or panels are present. Still missing? Go to the next section.

6. Plugin installed but not loading (failed to register)

Symptom. The install succeeded and the config looks right, but at startup dsh reports Plugin failed to register / Lifecycle timeout — or the plugin silently never loads.

Cause. Usually the runtime is too old (Node.js below 20), dependencies are missing (git installs need their own build step), declaration order collides with another plugin, or the entry was left enabled: false. A related failure mode is the sandbox: dsh runs read-only by default, so a plugin that needs disk or network access can be blocked at load time with Permission denied / Sandbox security policy violation.

Fix.

  1. Check the runtime: node -v — upgrade to 20.0.0 or higher (Node 22 LTS recommended).
  2. Source installs need their build: from the plugin directory run pnpm install && pnpm build, then restart.
  3. Reinstall cleanly: dsh plugin remove <package>, confirm the entry in cordis.patch.yml, then dsh plugin add <package> again.
  4. Confirm the entry is active: dsh plugin add writes enabled: true; if you hand-edited the YAML, make sure it is still there.
  5. If the error mentions the sandbox and the plugin is verified, launch with dsh --sandbox workspace-write (see Safety Guidelines).
  6. Installed from the dsh-market Web UI? Check Settings → Plugin Market for the plugin's status — the backend applies config and hot-reloads, so a failed state shows up there.

7. Slower after an upgrade / performance regression

Symptom. After upgrading dsh, opening an old session, resuming one, or long back-and-forth conversations visibly lag — the longer the session, the worse it feels. Or everything seems slower than the version you came from.

Cause. Most likely not your plugins. Long-session lag was a known issue in earlier releases: the session storage format was heavyweight, so once a conversation grew, opening, resuming and every turn paid extra memory and parsing costs.

Fix.

  1. Upgrade to the current stable line before judging: long-session lag was fixed in v0.1.5 (optimized storage format, lower memory usage), and as of 2026-09-29 npm latest is 0.2.0-rc.2. Run npm install -g @deepseek-ai/dsh@latest, restart, and re-test with the same long session. Most "it got slower after the upgrade" reports trace back to that known issue — upgrading resolves it. The experimental lines have caught up — next also points at 0.2.0-rc.2 and alpha at 0.1.7-alpha.2 — but diagnosing a slowdown on the alpha channel is the wrong starting point.
  2. Still slow? For very long contexts, launch with the Minimal profile (see GitHub discussion #5485): dsh --profile minimal loads only the persistent terminal and base tools, cutting what gets injected per session — use Standard for daily work, Minimal for marathon sessions.
  3. Still stuck: collect logs and report — include dsh --version, your launch command, session size (message count / file size), console errors and the comparison you ran, and open an issue on the official repository. The more complete the data, the faster the diagnosis.

8. A plugin broke after a dsh upgrade (pin it or roll back)

Symptom. dsh updates itself, or you run npm install -g @deepseek-ai/dsh@latest, and afterwards a plugin that worked yesterday refuses to load, loses its panel, or throws a registration error — sometimes only in one profile.

Cause. Two separate things break on an upgrade. The harness can change what it expects from a plugin: in v0.1.6-alpha.2 the official notes move plugin dependency resolution to runtime resolution and add runtime unloading, and they explicitly ask plugin authors to re-check their load and unload logic — so a plugin that was fine under the old model can fail until its author ships a fix. Or your own config is the mismatch: the entry sits in a profile you no longer launch, or two entries now collide after a re-order. Version churn is a live variable too: the 0.1.6 line shipped two alphas in two days (09-15 and 09-17), while the stable line held at 0.1.5-rc.3 until the 0.1.7-rc.2 flip on 09-28 — and the same day's 0.2.0-rc.1 reworks the plugin-management UI, so 0.2.0 previews carry a real compatibility tax (see the next section).

Fix.

  1. Scope it first — is it dsh or the plugin? Start the bare profile: dsh --profile minimal loads only the persistent terminal and base tools. If the problem disappears there, a plugin is implicated, not the harness. Note dsh --version and the exact launch command (including --profile <name>) before you change anything.
  2. Read the startup diagnostics. Since 0.1.6-alpha.2 (alpha channel), a failed start classifies the error and the waiting services and saves the full diagnostic to a log file — read that file before you start uninstalling things.
  3. Pin the harness if the whole install is wobbling: npm install -g @deepseek-ai/dsh@0.1.5-rc.2 — an exact version, never @latest. That is the rollback — the last stable-line version that worked for you is what you fall back to.
  4. Pin the plugin if only one is broken. Reinstall it from a tag instead of a moving branch: dsh plugin remove <package>, then dsh plugin add github:owner/repo#v1.2.3 (the #ref position takes a tag or a branch). If the plugin has no usable tag, disarm it rather than deleting it: set enabled: false on its entry in cordis.patch.yml and restart, so the config is still there when it works again.
  5. Back up before you touch anything: cp ~/.dsh/profiles/<name>/cordis.patch.yml ~/dsh-profile-backup.yml. A rollback that also costs you your whole plugin set is worse than the original bug.
  6. Check for the multi-instance conflict. If dsh reports that the session is occupied by another DSH instance, the official guidance is to exit that instance and retry — common when a server-resident instance and a local one share one profile (see Running dsh on a server).
  7. Then restart and verify. The plugin tree is assembled at startup, so nothing above counts as tested until a restart.

If you are on the alpha line on purpose, accept the trade: the release notes put the adaptation burden on plugin authors, and the ecosystem catches up plugin by plugin. When community plugins are load-bearing for you, stay on latest and let the alpha line settle.

9. Windows sandbox: 0xC0000142 and permission denials

Symptom. On Windows, every sandboxed shell command fails with 0xC0000142 (STATUS_DLL_INIT_FAILED), child-process output cannot be captured under the restricted sandbox (Access is denied), the desktop app cannot start a sandboxed PTY at all, or provisioning fails outright with SetNamedSecurityInfoW failed (Win32 5) — the reports cluster right after a harness upgrade, and new ones kept arriving throughout the 0.2.0-rc line.

Cause. The built-in Windows sandbox provisions per-directory ACLs at startup, and the on-record failure shapes now fall into three families. The 0xC0000142 family: non-elevated starts that fail to provision workspace-write and leave a broken, never-self-healing ACL behind (#8115); desktop runs where even harmless commands like pwsh/cmd echo die with the error (#8208, #8295); under 0.2.0-rc.1 an Electron-hosted child that cannot start at all (#8193); plus the earlier desktop-wide reports (#8142, #8130), the deterministic stdio-capture failures of the CLI/Web build with intermittent 0xC0000142 (#8143, #8141), the minimal-preset sandboxed PTY exiting 127 (#8158), and the early-October wave that put four new 0xC0000142 reports into a single 24-hour window — a Win10 LTSC start (#8877), a no-console launch (#8878), a DLL-init failure inside confined pwsh (#8890), and workspace-write provisioning dying in pwsh (#8897). The WRITE_OWNER family: when the workspace sits on a data drive (say D:\...), the drive's default inherited ACL only implies WRITE_DAC, while grantWrite opens the workspace root with WRITE_DAC | WRITE_OWNER — so provisioning fails with Win32 5, and from then on every sandboxed command in that session fails, including read-only ones, while the file read/write tools keep working (#8232, #8272, #8275, #8282, and a fresh WRITE_OWNER Win32 5 report, #8886). The regression family: 0.1.5 → 0.1.7-rc.2 dropped confined child processes into ConstrainedLanguage with every granted write denied (#8219), and workspace-write also broke git for Windows — MSYS binaries refusing to start and schannel unable to reach its key store (#8209). And a fourth wave landed within October 6–7 alone: the packaged desktop build where every workspace-write command exits 3221225794 / 0xC0000142 (#9031), every confined pwsh command dying the same way (#8991), Win11 pwsh tool spawns failing identically (#8990), plus #8971's useful control experiment — the same machine ran 0.1.5-rc.2's workspace-write sandbox without a hitch.

Fix.

  1. Scope it first: note the exact failure shape (every command vs intermittent, desktop vs npx, system drive vs data drive) and collect dsh --version plus the saved startup diagnostics log before changing anything.
  2. Upgrade to 0.2.0-rc.2 or newer and run the official one-shot repair: per the release notes, the Windows sandbox permission script now "combines diagnosis and repair in one authorized run, retaining pre-change backups and recovery commands". In a session, ask the agent to diagnose the sandbox permissions and let that run before hand-editing anything (on 0.2.0-rc.1 the same skill was diagnose-then-repair in two steps — #8272 records how much that gap mattered).
  3. For the WRITE_OWNER shape specifically: move the workspace back under your user directory, or grant your account explicit WRITE_OWNER on the data-drive root — which is exactly what the upgraded one-shot repair does, with a backup. As a fallback, launch once from an elevated shell so provisioning completes cleanly, then return to your normal (non-admin) terminal and re-test.
  4. If a broken ACL persists, remove the sandbox profile directory the failed provisioning created and let the next start re-provision it from scratch (back up cordis.patch.yml first — see section 8).
  5. Still failing? Add your report to the discussion cluster above with the diagnostics file attached — the shapes are being told apart by exactly these details.

10. Network and auth errors: proxy setups and "API key is invalid"

Symptom. Requests time out or hang behind a corporate proxy while the rest of the machine browses fine. Or the session answers with API key is invalid (401), Insufficient Balance (402) or a 403-style permission error.

Cause. dsh reaches providers over your environment's network: a proxy that npm honors but the dsh process does not (or the reverse) produces hangs and timeouts rather than clean errors. Invalid-key errors, meanwhile, are usually mundane — a key pasted with surrounding whitespace, a key bound to the wrong provider, a key set in the wrong profile's settings, or (famously) a login password autofilled into an API Key field, which 0.1.7-rc.2 specifically reduced.

Fix.

  1. Proxy first: set the standard variables for the process that launches dsh — HTTP_PROXY / HTTPS_PROXY / NO_PROXY — then restart dsh and retry. For slow plugin downloads (a different path), the registry mirror section of the install guide is the fix.
  2. Want a UI for this? kanneiren/dsh-network-settings (★107) diagnoses the real network path, DNS and first-failure point of the dsh process, and kriskite/dsh-network-proxy (★8) manages system/manual/direct proxy modes from a settings page.
  3. For API key is invalid: regenerate the key at the provider, paste it clean (no whitespace/newline), and confirm it belongs to the provider actually selected in Settings → Models.
  4. Read the status code before retrying: 401 means the key itself is wrong (fix the key), 402 means the account is out of credit (top up — see the balance guide), 403 means the key is valid but not allowed to use that model or region (switch model or account).

11. dsh: command not found

Symptom. The shell answers dsh: command not found; or the desktop app cannot find a dsh launcher on PATH (#8268); or a startup command that worked yesterday stopped existing after an update (#8242).

Cause. The CLI lives in your npm global prefix, so the failure is almost always one of three: the prefix directory is not on your PATH (typical with nvm/fnm/volta or a custom prefix), the install never finished, or a desktop app launched from the GUI inherits none of your shell's PATH additions. The web-flavored variant — you run dsh web and the shell answers zsh: command not found: dsh — is this same failure seen from the Web UI's front door: the CLI never started, so the web part never got a chance to fail.

Fix.

  1. Locate the binary first: npm prefix -g prints the global prefix — the dsh executable sits in the bin directory under it. Compare that directory against echo $PATH.
  2. Reinstall and open a fresh terminal (a new shell re-reads PATH): npm install -g @deepseek-ai/dsh.
  3. On the macOS / Windows desktop app, use the "Manage dsh command" menu-bar item shipped with 0.2.0-rc.2: it installs and manages the dsh command — plugins included — without requiring a separate Node.js or pnpm installation, which also covers GUI launches that never see your shell environment.
  4. As a stopgap, npx @deepseek-ai/dsh web runs the current version without any global install.

12. Desktop app: every command dies with 0xC0000142 and zero output (solved case)

Symptom. In the desktop app, every command returns 0xC0000142 and produces no output at all — no error text, nothing. The exact same command in a plain terminal on the same machine works fine. The report that nailed this shape (#8395) is marked solved.

Cause. 0xC0000142 is STATUS_DLL_INIT_FAILED: the sandboxed child process dies while being created, before it can emit anything. Under danger-full-access no restricted token is applied, so the same command runs — which is why "it works from the CLI" is the signature of this shape, not a contradiction. Controlled experiments in #8336 pinned the matrix: a restricted token (WRITE_RESTRICTED + Low integrity) combined with either console-isolation flag (CREATE_NO_WINDOW / CREATE_NEW_CONSOLE) kills the child every time; either factor alone is survivable. In the solved case the variable was the install location — the desktop app had been installed into a custom directory instead of the default one.

Fix.

  1. Confirm the shape first: CLI works, desktop dies silently → this section. Note dsh --version before changing anything.
  2. The solved fix (#8395): uninstall the desktop app and reinstall it into the default install location — do not pick a custom directory during setup.
  3. Official stopgap while you're blocked: set DSH_HOME to your harness home and launch the same entry point with ELECTRON_RUN_AS_NODE=1 — the workaround recorded in #8395.
  4. Verify: run a harmless command under workspace-write; output should come back. Still dying? Go back to section 9 and run the one-shot repair.

13. workspace-write grants never stick: the three ACL defects (and ERROR_NONE_MAPPED 1332)

Symptom. workspace-write is granted, but writes into subfolders of the workspace still fail; the desktop app keeps failing on the same workspace until you restart it; grantWrite fails with Win32 5 for a standard (non-admin) user whose workspace sits on a non-system drive; and when you try to hand-clean the ACL, icacls /remove answers ERROR_NONE_MAPPED (1332).

Cause. Discussion #8409 records three distinct authorization defects in the Windows ACL sandbox. First, subdirectories under a protected DACL never receive the grant, so per-folder writes keep being denied even after the root was authorized. Second, the desktop app evaluates the root grant once and caches the result without re-checking, so a stale failure keeps failing — restarting the desktop app re-runs the check and heals it. Third, a standard user on a non-system drive lacks WRITE_OWNER on the drive root, so grantWrite fails with Win32 5 — the same WRITE_OWNER family as section 9. The 1332 is a different beast: capability SIDs are not mapped to accounts, so icacls cannot remove them by name — the error means "nothing to map", not "your ACL is corrupt".

Fix.

  1. Run the official one-shot repair first (section 9, step 2) — it is the supported path and it keeps a backup.
  2. Desktop keeps failing on a workspace that should work? Restart the desktop app so the cached root grant is re-evaluated — the self-heal path documented in #8409.
  3. Standard user + data drive: move the workspace back under your user directory (or grant your account WRITE_OWNER on the drive root — which is what the one-shot repair automates).
  4. Do not fight icacls over ERROR_NONE_MAPPED 1332: unmapped capability SIDs cannot be removed by name. Let the official repair script handle the ACL instead — hand-stripping it can leave the sandbox profile in a worse state than the defect did.
  5. Verify: from the agent, create a file inside a subfolder of the workspace (defect one lives below the root), then restart the desktop app once and re-test.

14. dsh won't start at all: Smart App Control and antivirus TLS interception

Symptom. Two host-level blockers that look like dsh bugs but are not. On Windows 11 with Smart App Control enabled, dsh fails to boot (#8377). On the desktop app (0.2.0-rc.2) with certain antivirus suites, every HTTPS request from the host process fails and the UI only shows a generic error — login never completes (#8448).

Cause. Smart App Control blocks unsigned native modules, and dsh ships some — the boot fails before anything of ours logs an error; Event Viewer's CodeIntegrity log shows events 3077/3033 as the receipt. The AV failure shape is TLS re-signing: Kaspersky-class "encrypted connection scanning" intercepts HTTPS and re-signs it with the AV's own certificate, the host process rejects that chain, and all HTTPS traffic dies behind a generic UI error.

Fix.

  1. Smart App Control: check Event Viewer for CodeIntegrity 3077/3033 first — that is this shape's fingerprint. Then turn Smart App Control off; boot recovers (#8377). SAC has no per-app allowlist to add dsh to.
  2. Antivirus TLS: add the dsh-related domains to the AV's exclusion list, or disable the "encrypted connection scanning" feature — either restores the host's HTTPS (#8448).
  3. Verify: boot once (SAC) or sign in once (AV) after the change. Still a generic error? Collect the host logs and dsh --version, and compare against section 10's proxy shape before reporting.

15. Web UI says "authentication required" — or the port is busy

Symptom. You started dsh web (or npx @deepseek-ai/dsh web), but the page refuses with an authentication-required error; or the port is occupied; or typing dsh web only yields zsh: command not found: dsh. Search engines see all three phrasings as one question — they have three different answers.

Cause. The web UI's URL is printed by the command itself, and it carries the launch context for that run — the official docs are explicit that "the command prints its URL". Opening a bare 127.0.0.1:3080 by hand can therefore hit the authentication gate instead of the dashboard. A busy port means another dsh instance (or a leftover process) already holds 3080 — the multi-instance conflict of section 8. command not found is section 11's PATH problem, not a web UI one. And the gate itself is built-in by design: discussion #5936 — titled exactly dsh web authentication required — asks for a way to turn the mandatory token auth off, none has shipped, so LAN deployments meet the same wall as local ones.

Fix.

  1. Reopen the exact URL printed by dsh web — or just re-run the command and let it open the dashboard itself — instead of typing the bare address.
  2. Started over SSH? Printing the host URL only is expected behavior; open it in the browser of the machine that owns the forwarded port.
  3. Port busy: exit the other instance holding the session (section 8's multi-instance guidance), or start under a different port: dsh --profile web --port 8080.
  4. command not found: fix the install first (section 11 — npm global path, or the desktop app's "Manage dsh command").
  5. Genuinely exposing the dashboard beyond loopback (reverse proxy, shared LAN server)? The token gate still applies there too — it is not optional. The community route is hxy91819/dsh-auth (★6, GitHub API check 2026-10-03): a managed Caddy forward_auth edge with Argon2id-hashed admin login, while dsh itself stays on loopback (its showcase thread is #3231). Capable but early — it requires Linux x64/ARM64, systemd and Node 24.7+, and a star count that low means a small user base — so read its README before putting it in front of a public URL.
  6. Going further: the frame-verified Web UI guide walks the whole interface; the remote & mobile collection gathers phone/remote clients (dsh-pocket, dsh-web and friends); and remote access covers tunnels for reaching the dashboard from outside.
  7. Verify: the printed URL loads the dashboard and the composer accepts input once a workspace is chosen.

16. API key is invalid (401) — when the key is not actually the problem

Symptom. A session or run dies with the literal error API key is invalid, usually with a 401, or with a 403-style permission error. The searches that land here type the exact phrase — and in the recorded cases the key was sometimes fine: the same key worked in one surface and failed in another, or the message appeared while the key was demonstrably correct.

Cause. Three mundane key problems cover most hits: the key was pasted with surrounding whitespace or a newline, the key belongs to a different provider than the one selected in Settings → Models, or the key was saved into a different profile's settings than the one you launched. Beyond those, discussion #5794 records the surface-mismatch shape in two cases — the Web UI and a headless run do not read the same stored credential, so one works while the other gets rejected. And two further reports (#3073, #3222) show a provider adapter surfacing a non-auth failure as API key is invalid — so the error text alone does not prove the key is bad.

Fix.

  1. Read the status code before retrying (the triage of section 10): 401 means the key itself was rejected — fix the key; 402 means the account is out of credit; 403 means the key is valid but not allowed for that model or region — switch model or account.
  2. Regenerate the key at the provider, paste it clean (no whitespace/newline), and confirm it belongs to the provider actually selected in Settings → Models.
  3. Surface mismatch (#5794): if the Web UI works but a dsh --profile headless run fails (or the reverse), put the key where the failing surface reads it — the DEEPSEEK_API_KEY environment variable or repo-root .env for headless runs — then retry the same command.
  4. Key verifiably correct and the error persists across surfaces? Treat it as a suspected misclassification: capture the full error output plus dsh --version, and compare against #3073/#3222 before rotating credentials again.
  5. Behind a proxy? Section 10's proxy shape produces hangs and timeouts rather than clean 401s — rule it out there before blaming the key.
  6. Deleted the key at the provider by accident, and now dsh will not accept a new one? That is a recorded gap (#8988, echoing the earlier closed report #7625): the desktop and web clients currently offer no update or delete-and-reset path for a stored credential. Interim: headless runs can read a fresh key from the DEEPSEEK_API_KEY environment variable (step 3's route); for the web and desktop surfaces there is no in-product reset yet — add your case to #8988 and watch the thread. The brand-form search deepseek harness api key is invalid lands on this section.

17. Output token limit reached — two ceilings, two fixes

Symptom. The answer stops mid-way with an output-token-limit error, or long turns get cut off — the exact phrase people search is output token limit reached (open reports: #1166, #5970). The brand-prefixed searches — deepseek harness token limit, deepseek harness output token limit — land in the same place. A related but distinct failure: CONTEXT_WINDOW_EXCEEDED right after a compression pass.

Cause. Two different ceilings get confused here. The output limit: every model row carries a Max output tokens value (the custom-model row shows 32K as its placeholder) — a single reply that runs past it is truncated. The context limit: the conversation as a whole runs out of window, and compression is supposed to fold history before that happens — but #8498 records compression spinning and then misjudging the session as CONTEXT_WINDOW_EXCEEDED, and #8494 records the usable headroom collapsing after a large headroom value. So the "limit reached" you see may be the compression machinery misfiring, not a genuinely too-big session.

Fix.

  1. Cap the reply, not the session: on Settings → Models, set the row's Max output tokens field (custom model rows expose it directly; placeholders 256K/32K; leave empty to inherit the provider's defaults) — raise it for models that truncate long answers.
  2. For a session that has genuinely grown huge, split it: start a fresh session and carry over a summary — the context compaction guide explains how dsh folds history and what the three compaction triggers are.
  3. Seeing CONTEXT_WINDOW_EXCEEDED right after (or during) a compression pass? That is the #8498 shape: note dsh --version and the session size, restart and retry once, then add your report to the discussion with the diagnostics attached.
  4. Repeated mid-answer cuts on a small task point at the provider, not dsh: check the provider's own usage page for length or rate caps on your plan before changing any dsh setting.
  5. Still hitting it: dsh --version, the launch command and the full error text into the discussion cluster (#1166, #5970) — that is where this shape is being told apart.

18. Out of memory (OOM) — what gets killed is the process, not the session

Symptom. On Linux the dsh process vanishes mid-run, leaving the terminal with a bare Killed (or exit code 137); dsh web dies after running for a while, with OOM (out of memory) entries in the logs. The exact phrase people search is dsh oom — one warning first: the wall of DSH medical-finance content in the results (Disproportionate Share Hospital, a US Medicaid term) has nothing to do with this tool; the real peer cases live in the GitHub discussions.

Cause. OOM is memory exhaustion at the operating-system level — the dsh process (or the container/cgroup it runs in) asks for more memory than the limit allows, and the kernel kills it to survive. That is a different failure from section 17's ceilings: an exhausted context window raises a model-side error such as CONTEXT_WINDOW_EXCEEDED and the session survives; OOM takes the whole process down. Two documented shapes: running through a one-off npx makes it more likely (the GitHub report "Linux: OOM when running dsh via npx — use global install"; the official fix is exactly that), and #8639 records the long-running dsh web case — RSS grows with session count until a 1GiB cgroup limit OOM-kills it.

Fix.

  1. Don't run dsh long-term through npx — install globally: npm install -g @deepseek-ai/dsh, then start with dsh. That is the official disposition for the report, and it also fixes section 11's command not found.
  2. Long-running dsh web getting killed (the #8639 shape): check whether its systemd/cgroup unit enforces a hard cap such as 1GiB — raise or remove MemoryMax, then watch whether RSS keeps growing with session count; restart dsh web periodically if your sessions are memory-hungry.
  3. Triage before touching anything: CONTEXT_WINDOW_EXCEEDED / token-limit text in the error → section 17 and the context compaction guide; a bare Killed plus Out of memory: Killed process in dmesg → this section's OOM.
  4. Containers and small VPS: add swap or raise the memory limit for the dsh container; budget at least 2GiB of headroom when the web UI and several sessions run together.
  5. Still reproducing: bring dsh --version, the deployment shape (npx / global / Docker / cgroup limit) and the relevant dmesg lines to the discussions — the #8639 thread is collecting exactly these.

19. Desktop app fails to launch: the late-September startup wave

Symptom. Four distinct desktop-side launch failures clustered in official discussions from late September to early October 2026: on Windows 11 the app dies while loading its V8 startup snapshot (#8776); launching as administrator exits with code 18 (#8787); the host process crashes with 'prepare' is undefined — once after a plugin id conflict (#8822), and again on resume after a profile package.json was corrupted by a BOM (#8837); and the familiar 0xC0000142 returned as a three-report cluster (#8771, #8772, with #8775 analyzing the DACL capability-SID mechanism behind it).

Cause and fix, per shape.

  1. V8 startup snapshot failure (#8776): the desktop binary's snapshot fails to load, typically after a broken or half-applied update. Reinstall the desktop app from a fresh download rather than reusing the old install directory, and check dsh --version from the CLI to confirm the core itself is healthy.
  2. exitCode 18 as administrator (#8787): elevation changes the environment the app expects (user-directory redirection, a different PATH). First run it as your normal user; if elevation is genuinely required, launch from an already-elevated shell with a clean environment instead of right-clicking a stale shortcut.
  3. 'prepare' is undefined (#8822, #8837): a host-side crash, not an in-plugin error. In #8822 two plugins registered conflicting ids and a lookup came back empty; in #8837 a package.json saved with a UTF-8 BOM broke profile parsing and the same error resurfaced on resume. Remove the offending plugin or re-save the file as UTF-8 without BOM, then cold-start once before resuming any session. A third shape arrived in October (#8924): with a web profile carrying its own copy of @deepseek-ai/dsh-tools (a dual-package setup used for local plugin dev), every tool call died with the same reading 'prepare' error while text-only turns survived — remove the profile-local duplicate so a single dsh-tools copy resolves.
  4. 0xC0000142, third appearance (#8771, #8772, #8775): the same STATUS_DLL_INIT_FAILED family as sections 9 and 12, this time reported in both Chinese and English. #8775's analysis points at capability SIDs in the child process's DACL. Run the section 9 one-shot repair first — it remains the supported path for this whole family.

20. Old sessions stop opening after an upgrade: the session-format codecs

Symptom. After moving to a newer dsh, a previously fine session refuses to open with a SessionFormatError-style message. Two shapes are on record: the v0→v1 codec rejects sessions written by 0.1.0-rc.6 / 0.1.1-rc.2 because their subagent/descriptor events carry version: 2 where the codec requires version: 3 (#8868) — any deployment whose history contains subagent sessions was blocked from upgrading by this; and the v3→v4 codec refuses legitimately-written logs whenever a system/message does not sit at the very first surface node of the file (#8888).

Cause. Session logs are versioned, and each codec migration validates strictly: the v0→v1 migration pinned an exact event version, and the v3→v4 foldSurface guard assumed a system/message must be the first surface node — both assumptions reject real logs that older releases wrote legally.

Fix.

  1. Note the exact error text and your dsh --version — the two shapes are told apart by which migration complains.
  2. If the sessions opened fine before an upgrade, the fastest working path is the section 8 rollback: pin the harness back to the version that wrote those logs (npm install -g @deepseek-ai/dsh@<version>), let the sessions open, and export what you need.
  3. Do not hand-edit session files to satisfy a validator — a malformed edit can make the log permanently unreadable. Back the file up instead and add your report to #8868 / #8888 with the error text; both threads are where the follow-up fixes land.

21. Security advisory: sandbox-escape disclosure via the local control plane (#8887)

What happened. A public disclosure in the official discussions (#8887, severity: high) describes a chain that lets a confined agent escape the sandbox and bypass the approval policy through dsh's own local control plane at 127.0.0.1:3080: a single command inside any sandboxed session (even under a read-only file policy) is enough to reach arbitrary file writes as your user, with no approval prompt. It was verified on dsh 0.2.0-rc.2 on Linux/WSL2 and is described as platform-independent.

What to do now.

  1. Keep the web UI on its default loopback bind — the attack path starts from anything that can reach 127.0.0.1:3080, so never rebind it wider and never tunnel port 3080 to a network you don't fully control (see the remote access guide for what safe exposure looks like).
  2. Treat "sandboxed" as "hardened, not a security boundary" until a fix ships: don't point sandboxed sessions at untrusted repositories or prompt-injection-prone content on machines that hold anything valuable.
  3. Update dsh as fixes land and follow #8887 — the disclosure thread is the canonical place for the official response and any patched release.

22. Security advisory: a workspace rooted at / disables the sandbox (#9026)

What happened. A second sandbox disclosure, three weeks after the #8887 control-plane escape (section 21): a session or workspace whose root is / passes resolveWorkspaceRoot()'s only check — isAbsolute() — and flows unchanged into writableRoots(), so the writable set becomes ['/', '/tmp', tmpdir()]. Every enforcing backend then grants read-write on the entire filesystem: bwrap via --bind / /, Landlock because the RW rule overrides the read-only rule, sandbox-exec via a writable prefix of /. Both entry points go unvalidated: session.create({ cwd: '/' }) and workspace.create({ path: '/' }).

What to do now.

  1. Never run sessions or workspaces rooted at / — and audit any tooling that creates sessions for you — until a fix ships. That is the whole defense for now.
  2. Everything in section 21 still applies: loopback-only web UI, no tunneling of port 3080, the sandbox treated as hardening rather than a boundary.
  3. Update dsh as fixes land and follow #9026 — the disclosure thread is where the official response lands.

23. Desktop stability wave: crash loops, wiped plugin deps, Electron 44 (October 2026)

Symptom. Four desktop-side shapes clustered in the discussions within a single week: the app dies on every boot and only a full plugin disable recovers it (#8995); after a desktop upgrade a plugin silently stops working with no error anywhere (#9030); the host process dies with 0xC0000409 while the renderer keeps crashing on Electron 44 / Chromium 152 (#8972), with renderer OOM crashes as a sibling report (#8932); and one power user published a 22-item reproducible stability list spanning plugin loading, dependency trees, session files and configuration (#8951).

Cause and fix, per shape.

  1. Startup crash loop (#8995). An unhandled rejection inside one third-party plugin is treated as fatal by the host's fail-loud handler, so every boot re-runs the same failure — six crashes in three minutes in the recorded case. There is no automatic safe mode yet, so the recovery is manual: set enabled: false on the suspect plugin in ~/.dsh/cordis.patch.yml (or move the file aside), start again, then re-enable plugins one by one to find the culprit.
  2. Plugin silently dead after an upgrade (#9030). The recorded case: a desktop upgrade wiped a plugin's runtime dependency directories while the package manager's state file still listed them — contents gone, no error surfaced anywhere. If a plugin's panel vanishes after an upgrade with no error in sight, reinstall it (dsh plugin remove + dsh plugin add, or the desktop plugin manager) so its dependencies are materialized again.
  3. Repeated host/renderer crashes on 0.2.0-rc.2 (#8972, #8932). Host exits 0xC0000409 plus recurring renderer crashes on Electron 44 / Chromium 152, with intervals shrinking between crashes; a sibling report logs renderer OOM crashes. Attach the diagnostics bundle the desktop exports, note dsh --version, and add your case to the threads — the shapes are being told apart by frequency and by which process dies.
  4. The 22-issue stability list (#8951). A 30-day, 100+-session write-up ranks three fixes above all others: plugins that register but neither load nor error; plugin mount failures that take the whole client down (fail-closed); and session files with no official verify/repair tool — the last one is section 20's codec territory. Worth reading before you debug: your shape may already be item P-01 through P-22 on the list.

Still stuck?

  • Installing Plugins Safely — the install methods, profiles and CLI cheat sheet
  • Configuration Guide — bundles, profiles and patches: which layer are you actually editing?
  • The dsh CLI cheat sheet — every command, flag and mode on one printable page
  • DeepSeek Harness rollback walkthrough — snapshot restore and crash rescue with dsh-undo-savepoint, before you reinstall anything
  • Submit a plugin — if a plugin's README disagrees with what happens on your machine, open an issue on its repository with your exact dsh --profile command and the error text; maintainers fix discrepancies fastest that way.
AD

DSH Plugins is an independent community directory of DeepSeek Harness plugins. Not affiliated with or endorsed by DeepSeek. Third-party plugins are not security-audited — review the source before installing.

New DeepSeek Harness plugins, weekly. No spam.