DeepSeek Harness 0.2.1 sidebar 405: webRuntime removed
After upgrading to DeepSeek Harness (DSH) 0.2.1, the sidebar is still there, but Markdown preview will not open, the file tree is blank, and git actions do nothing. Every one of those requests returns 405 with an empty body. This is not networking or permissions: the plugin waits for webRuntime, which 0.2.1 removed in favour of webStartup, so it stays pending and none of its routes are mounted.
DeepSeek Harness empty-body 405 is an unmounted route fingerprint
When every API from one plugin returns an empty 405 and its row is pending, the service name is the cause; a single failing endpoint points at a routing mistake instead. Use the shape of the response to separate the cases:
| Observation | Meaning |
|---|---|
| One endpoint returns 405, others work | Method mismatch or a wrong route |
| Every endpoint of one plugin returns an empty 405 | The plugin never mounted; requests hit the static fallback |
| 404 with HTML | The path does not exist |
| 405 with a JSON error body | Business logic rejected the call |
According to the source review in the discussion, app-boot/src/index.ts:1072-1074 does not re-evaluate an entry that is pending, and frontend-static/src/index.ts:122-125 hands an unmatched POST to the static handler, which answers with an empty 405 (#10027). For normal sidebar usage, see the sidebar plugin tutorial.
Find the plugin before repairing anything:
- Search the plugin list for pending — collect every row and its waiting service; expected: one or more rows name
webRuntime. - Match the failing APIs to a plugin — compare the broken features with the plugin that provides them; expected: one plugin covers all failing endpoints.
- Bisect if several plugins are pending — disable one at a time and restart; expected: the 405 set disappears when the right plugin is off.
- Use community tooling if available — the activation-doctor plugin lists pending rows with their missing services; expected: the same mapping with less manual work.
What 0.2.1 changed in the DSH web service
The public web service was renamed and the trust configuration changed with it; a plugin that migrates only half of that pair stays pending. The chain:
- The old plugin declares
inject: ['webRuntime']— it waits for that service at startup, so the row does not start on a 0.2.1 host. - 0.2.1 never registers
webRuntime— the service never appears, so the wait never ends. - The entry stays pending — the host logs a warning instead of failing, so startup succeeds and the problem stays quiet.
ctx.webRuntime.register(...)never runs — no routes are registered.- A request arrives — no dynamic route matches, and the static fallback returns an empty 405.
The official upgrade guide records the migration (web-listener-trust-config), but it is easy to miss in release notes.
Three DeepSeek Harness recovery paths
Bottom line: upgrade when the author has migrated, rename the service locally when they have not, and disable the plugin when it is not essential.
Repair 1: upgrade to a build that targets webStartup
The cleanest fix is a newer plugin release, provided the author has migrated. In the discussion's example, the sidebar plugin at 0.24.1 still used webRuntime, while 0.28.0 had moved to webStartup:
- Read the plugin page — check the latest version and whether its changelog mentions
webStartup; expected: the release notes confirm the migration. - Update from the plugin market — install the newer version and wait for it to finish; expected: the package under the profile is replaced.
- Restart DSH — relaunch and inspect the plugin state; expected: pending changes to active.
- Exercise the sidebar — open preview, the file tree, and a git action in turn; expected: no 405 responses.
- Check for leftovers — if it is still pending, look for a stale version directory under the profile; expected: only one copy of the plugin remains.
Repair 2: rename the service in the local plugin artifact
When no compatible release exists, the built artifact can be patched by hand; the changes are few but they are not durable.
- Locate the installed package — for example
~/.dsh/profiles/<profile>/node_modules/dsh-better-sidebar; expected: you are editing the artifact the profile actually loads. - List every occurrence — open
lib/index.jsand search forwebRuntime; expected: a complete inventory of references. - Change the declaration — replace
webRuntimeinsideinjectwithwebStartup; expected: the row can resolve the new service. - Change the call sites — replace
ctx.webRuntimewithctx.webStartup, checking whether method names also differ; expected: registration code compiles against the new API. - Restart and record — verify the plugin is active and the APIs respond, then note the patch; expected: you can reapply it after the next update.
An update overwrites the change, method signatures may differ, and dependency cleanup can remove the edit, so this patch is temporary.
Repair 3: disable the plugin and use an alternative
If the affected plugin is not essential, disabling it removes both the pending row and the 405s immediately.
- Disable the plugin — find the one still injecting
webRuntimeand switch it off; expected: the pending row disappears after restart. - Restart and confirm — reload DSH and retry the affected endpoints; expected: no more empty 405 responses and other plugins still load.
- Replace the capability — use a built-in feature or a plugin already compatible with 0.2.1; expected: the workflow continues without the broken package.
- Re-enable later — turn it back on once the author ships a compatible version; expected: the capability returns without manual patching.
Verify DSH fixes and avoid regressions
Active status is necessary but not sufficient; every API from the plugin must answer normally after a restart. Verify:
- Check the row — it must read active, not pending; expected: the plugin mounted.
- Exercise each API — preview, file tree,
git status, and save; expected: all respond successfully. - Read the status codes — inspect the browser's developer tools; expected: 200 or 204, never an empty 405.
- Restart twice — reload DSH again; expected: the state is stable and load order does not push it back to pending.
- Add an unrelated plugin — install something else and restart; expected: the repaired plugin is not displaced.
Avoid these traps:
- Do not treat the 405 as a backend routing bug; inspect plugin state first and save time.
webRuntimewas a public service name, so removing it is a breaking change; check compatibility before upgrading a host.- Patching
node_modulesis not a long-term solution, so record the change and ask the author to migrate. - Trust configuration also changed in 0.2.1; if the service name is fixed but requests still fail with 403 or 401, inspect
trustedHostsand do not blame a DSH plugin permission setting for a routing problem. - Back up the profile before editing, because the same directory holds settings and session data.
DeepSeek Harness webRuntime FAQ
Q: Why does DeepSeek Harness 0.2.1 return empty 405s from the sidebar APIs? A: DeepSeek Harness returns empty 405s because a plugin still injects webRuntime, which 0.2.1 removed in favour of webStartup. The plugin stays pending forever and never registers its routes, so requests fall through to the static handler; upgrade the plugin or change its inject entry.
Q: What is the difference between webRuntime and webStartup in DeepSeek Harness? A: DeepSeek Harness webRuntime and webStartup are both entry points for plugins that expose web services; 0.2.1 deleted webRuntime, kept webStartup, and changed the trust configuration. A plugin that still declares inject: webRuntime waits for a service that never appears, so every route it would have registered is absent.
Q: How do I confirm a DeepSeek Harness 405 comes from a pending plugin, not a wrong route? A: A DeepSeek Harness 405 from a pending plugin comes with a pending (waiting for service: webRuntime) row and an empty body. A routing mistake usually returns 404 or a body with an error; a pending plugin sends every request to the static fallback, so all of its APIs fail together.
Q: Can I rename webRuntime references in a DeepSeek Harness plugin without an update? A: A DeepSeek Harness plugin can be patched by renaming inject and the ctx.webRuntime call sites to webStartup in the built artifact. This is a local patch that the next update will overwrite, so it is a stopgap until a 0.2.1-compatible release exists.
FAQ
DeepSeek Harness returns empty 405s because a plugin still injects webRuntime, which 0.2.1 removed in favour of webStartup. The plugin stays pending forever and never registers its routes, so requests fall through to the static handler; upgrade the plugin or change its inject entry.
DeepSeek Harness webRuntime and webStartup are both entry points for plugins that expose web services; 0.2.1 deleted webRuntime, kept webStartup, and changed the trust configuration. A plugin that still declares inject: webRuntime waits for a service that never appears, so every route it would have registered is absent.
A DeepSeek Harness 405 from a pending plugin comes with a pending (waiting for service: webRuntime) row and an empty body. A routing mistake usually returns 404 or a body with an error; a pending plugin sends every request to the static fallback, so all of its APIs fail together.
A DeepSeek Harness plugin can be patched by renaming inject and the ctx.webRuntime call sites to webStartup in the built artifact. This is a local patch that the next update will overwrite, so it is a stopgap until a 0.2.1-compatible release exists.
Related Terms
- webRuntime
- webRuntime is the web runtime service that DeepSeek Harness exposed to plugins before 0.2.1. Plugins used it to register routes and middleware; from 0.2.1 it no longer exists and webStartup replaces it.— https://github.com/deepseek-ai/deepseek-harness/discussions/10027
- webStartup
- webStartup is the web startup service introduced in 0.2.1. It takes over route registration and trusted-host configuration from webRuntime, so plugins must migrate both the inject declaration and their call sites.— https://github.com/deepseek-ai/deepseek-harness/discussions/10027
- empty-body 405
- An empty-body 405 is a 405 whose response body is empty, meaning a static resource handler rejected the method rather than business logic returning an error. In DSH it usually indicates that the dynamic route was never mounted.— https://github.com/deepseek-ai/deepseek-harness/discussions/10027
Sources
- #10027 — A stale inject service name leaves third-party plugins silently pending and all sidebar APIs return an empty 405· deepseek-ai (GitHub Discussions)
- DeepSeek Harness 0.2.1 upgrade guide (web listener trust configuration)· deepseek-ai (GitHub)