You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Web boot aborts when two plugin client bundles declare the same top-level name (SyntaxError kills the whole chunk)
#12932
A third-party plugin's client.js declaring one variable at module top level can take the entire Web GUI down. DSH concatenates plugin client bundles into a single script scope, so a top-level name collision between two plugins is a parse-time SyntaxError, not a runtime error in one plugin: the whole chunk fails to evaluate, every client plugin goes offline together, and web boot aborts.
Suggestions: (1) give each module its own scope, and (2) carry the underlying exception into the boot-failure record.
After restarting the app, the Web GUI would not open. The boot log reported:
--- error ---
Error: web boot: 1 entry did not activate
dsh-linglu-balance: import failed (see console for the import error)
at file:///Applications/DeepSeek%20Harness.app/Contents/Resources/app.asar/lib/main.js:20648:15
The actual cause appears further down in the same log, in the renderer console section:
dsh-app://app/plugins/??dsh-linglu-balance/client.js&rev=…:1
Uncaught SyntaxError: Identifier 'BALANCE_ROUTE' has already been declared
Root cause
The browser loads one concatenated script rather than one script per plugin:
All of these files are evaluated as a single script, so they share one top-level lexical scope. Two plugins each had:
// plugin A client.jsconstBALANCE_ROUTE="/plugins/dsh-lk888-balance/balance";constCSS=`…`;constzh={…};consten={…};// plugin B client.jsconstBALANCE_ROUTE="/plugins/dsh-linglu-balance/balance";constCSS=`…`;constzh={…};consten={…};
The second declaration of BALANCE_ROUTE (and CSS, zh, en) is a redeclaration, which is a parse-time error — so even the first, otherwise-valid plugin never runs.
Per-file checks cannot see this: node --check a/client.js and node --check b/client.js both pass, and installing either plugin alone works. The defect only detonates when a second plugin of the same shape is installed.
Why I think this is a Host-side issue
The module convention is clear — the official template (templates/decoration/client.js) keeps the top level to a single window.__ModuleLoader__.load({...}) and nests everything inside factory(require){}. But:
Blast radius. One third-party file's stray const costs the whole UI and every plugin, and it surfaces at restart, far from the action that caused it.
Poor diagnosability.web boot: 1 entry did not activate / import failed carry no reason. The real error was already in the same log, just not in the failure record itself.
No isolation. If each module were evaluated in its own function scope (or wrapped as (function(){ … })() before concatenation), this mistake would cost that plugin and nothing else. Third-party code getting scoping wrong is an expected ecosystem behavior and should not be amplified into a global outage.
Suggested fixes
A. Give each module its own scope (root fix).
(function(){/* the plugin's client.js source */}).call(globalThis);
or any equivalent that prevents lexical declarations from crossing file boundaries.
B. Attach the underlying error to the failure record (cheap).
web boot: 1 entry did not activate
dsh-linglu-balance: SyntaxError: Identifier 'BALANCE_ROUTE' has already been declared
C. Optional: check top-level bindings at install time, so the problem is caught before the next restart instead of after.
Evaluating both files in one script yields SyntaxError: Identifier 'SHARED' has already been declared, and nothing in the chunk executes.
Convention for plugin authors
Keep the top level of client.js to exactly one statement — window.__ModuleLoader__.load({ id, factory(require){ … } }) — and put constants, styles, dictionaries, components and helpers inside the factory body.
A checker is easy to build: parse the bundle, collect top-level bindings, and evaluate the concatenation of all bundles once.
Note on scope of this report
I verified this was not a widespread ecosystem problem: of the 40 client bundles installed in my profile, all keep the top level to the load(...) call. The two offenders were both plugins I had written myself, and both are fixed. I am reporting it because the failure mode (one plugin → whole GUI down, with no reason in the record) seems worth hardening against.
Written with the help of an AI agent inspecting the crash log and the concatenated bundle URL.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Summary
A third-party plugin's
client.jsdeclaring one variable at module top level can take the entire Web GUI down. DSH concatenates plugin client bundles into a single script scope, so a top-level name collision between two plugins is a parse-timeSyntaxError, not a runtime error in one plugin: the whole chunk fails to evaluate, every client plugin goes offline together, and web boot aborts.Suggestions: (1) give each module its own scope, and (2) carry the underlying exception into the boot-failure record.
Environment
@deepseek-ai/dsh-desktop0.2.2-rc.1~/Library/Logs/DeepSeek Harness/crash-2026-11-11T05-29-37-577Z-web-boot.logSymptom
After restarting the app, the Web GUI would not open. The boot log reported:
The actual cause appears further down in the same log, in the renderer console section:
Root cause
The browser loads one concatenated script rather than one script per plugin:
All of these files are evaluated as a single script, so they share one top-level lexical scope. Two plugins each had:
The second declaration of
BALANCE_ROUTE(andCSS,zh,en) is a redeclaration, which is a parse-time error — so even the first, otherwise-valid plugin never runs.Per-file checks cannot see this:
node --check a/client.jsandnode --check b/client.jsboth pass, and installing either plugin alone works. The defect only detonates when a second plugin of the same shape is installed.Why I think this is a Host-side issue
The module convention is clear — the official template (
templates/decoration/client.js) keeps the top level to a singlewindow.__ModuleLoader__.load({...})and nests everything insidefactory(require){}. But:constcosts the whole UI and every plugin, and it surfaces at restart, far from the action that caused it.web boot: 1 entry did not activate/import failedcarry no reason. The real error was already in the same log, just not in the failure record itself.(function(){ … })()before concatenation), this mistake would cost that plugin and nothing else. Third-party code getting scoping wrong is an expected ecosystem behavior and should not be amplified into a global outage.Suggested fixes
A. Give each module its own scope (root fix).
or any equivalent that prevents lexical declarations from crossing file boundaries.
B. Attach the underlying error to the failure record (cheap).
C. Optional: check top-level bindings at install time, so the problem is caught before the next restart instead of after.
Minimal reproduction
Evaluating both files in one script yields
SyntaxError: Identifier 'SHARED' has already been declared, and nothing in the chunk executes.Convention for plugin authors
Keep the top level of
client.jsto exactly one statement —window.__ModuleLoader__.load({ id, factory(require){ … } })— and put constants, styles, dictionaries, components and helpers inside the factory body.A checker is easy to build: parse the bundle, collect top-level bindings, and evaluate the concatenation of all bundles once.
Note on scope of this report
I verified this was not a widespread ecosystem problem: of the 40 client bundles installed in my profile, all keep the top level to the
load(...)call. The two offenders were both plugins I had written myself, and both are fixed. I am reporting it because the failure mode (one plugin → whole GUI down, with no reason in the record) seems worth hardening against.Written with the help of an AI agent inspecting the crash log and the concatenated bundle URL.
All reactions