Skip to content

fix(desktop): resolve the plugin-SDK namespaces lazily so bundler order can't break runtime plugins - #107518

Closed
ligorx wants to merge 1 commit into
NousResearch:mainfrom
ligorx:fix/desktop-plugin-sdk-globals
Closed

ligorx wants to merge 1 commit into
NousResearch:mainfrom
ligorx:fix/desktop-plugin-sdk-globals

Conversation

@ligorx

@ligorx ligorx commented Sep 10, 2026

Copy link
Copy Markdown

What breaks

On the 2026-09-10 packaged Windows build (main @ 073c57872a4) every runtime (disk) desktop plugin fails to load — reproducibly, for two unrelated plugins:

[plugins] runtime load failed (provider-usage) TypeError: Cannot convert undefined or null to object
  (…/resources/app.asar.unpacked/dist/assets/sdk-RKHbz2ri.js:5)
[plugins] runtime load failed (stt-switch) TypeError: Cannot convert undefined or null to object
  (…/resources/app.asar.unpacked/dist/assets/sdk-RKHbz2ri.js:5)

Capabilities → Plugins lists both desktop plugins as failed with that message, and none of their contributions register (status-bar chips, palette commands). It hits unrelated plugins, so this is not plugin-specific: no disk plugin can load at all.

Why

apps/desktop/src/sdk/runtime.ts materialises its namespace map at module init:

const GLOBALS = { __HERMES_PLUGIN_SDK__: sdk, … } as const

In that build the bundler emitted this module's body before ./index assigns its namespace binding:

built chunk (dist/assets/sdk-*.js) offset
var bg={__HERMES_PLUGIN_SDK__:Lb, …} (this file) 157012
var Lb=t({…}) (the ./index namespace) 231521

so bg.__HERMES_PLUGIN_SDK__ was captured as undefined. The loader then runs installPluginSdk() / shimUrl(), whose Object.keys(GLOBALS[key]) throws exactly this TypeError; because sdkImportMap() builds all four shims eagerly and only caches them on success, one unassigned namespace kills the map for every plugin.

The previous packaged build (2026-08-31) emitted the same two statements in the opposite order (var kp=… @101714, var tm=… @116891) and worked. Same source, different bundler order — which is why this appeared only with the rebuild, and why the capture is the bug.

Fix

Resolve the namespaces inside a function, so they are read at call time (plugin load, when they are guaranteed assigned) instead of at module-init time. Nothing else changes.

Verification

  • Node reproduction of the failing shape: eager capture + later assignment → TypeError: Cannot convert undefined or null to object; the lazy form → the namespace's live keys, globals installed.
  • Bundle offsets above, read from the failing build's chunk.
  • The same change applied to that build's chunk in place clears the failure path on the affected machine; the renderer reload is the last step (I will confirm in a comment).
  • No test added: the failure depends on the bundler's emission order and cannot be reproduced under vitest — the invariant is now structural (no module-scope capture).

…er can't break runtime plugins

`apps/desktop/src/sdk/runtime.ts` captured its namespace map at module init:

    const GLOBALS = { __HERMES_PLUGIN_SDK__: sdk, ... } as const

The 2026-09-10 packaged build emitted that map BEFORE `./index` assigns its
namespace binding (minified: `var bg={...}` @157012, `var Lb=t({...})` @231521),
so the SDK namespace was captured as `undefined` and `Object.keys(undefined)`
inside `shimUrl` threw for EVERY runtime (disk) plugin:

    [plugins] runtime load failed (provider-usage) TypeError: Cannot convert
      undefined or null to object (.../assets/sdk-RKHbz2ri.js:5)

`installPluginSdk()`/`sdkImportMap()` build all four shims eagerly, so one
unassigned namespace killed the whole map for every plugin; the 2026-08-31 build
emitted the same two statements in the other order, which is why this only
appeared with the rebuild.

Resolving the namespaces inside a function reads them when they are guaranteed
assigned (plugin load) instead of at module-init time. Nothing else changes.
@ligorx

ligorx commented Sep 10, 2026

Copy link
Copy Markdown
Author

Confirmed on the affected machine (Windows, main @ 073c57872a4, the failing chunk with this change applied in place):

  • After an app restart, desktop.log carries none of the previous [plugins] runtime load failed (…) TypeError: Cannot convert undefined or null to object lines — both provider-usage and stt-switch threw those on every boot before this.
  • A runtime-plugin hot-reload in the same session evaluates the plugin module cleanly (probe line in the renderer console, no loader error), i.e. installPluginSdk() / sdkImportMap() now build the shim map and the plugins register — their status-bar chips are back.

So the failure is confirmed fixed by this change; the patch in this PR is the same code path, made at the source.

@alt-glitch alt-glitch added type/bug Something isn't working P1 High — major feature broken, no workaround comp/desktop Electron desktop app (apps/desktop/*) comp/plugins Plugin system and bundled plugins duplicate This issue or pull request already exists labels Sep 10, 2026
@alt-glitch

Copy link
Copy Markdown
Contributor

This was generated by AI during triage.

Duplicate of #107303 — byte-for-byte the same approach (module-scope GLOBALS replaced by a call-time namespace function in apps/desktop/src/sdk/runtime.ts), filed earlier. Tracking issue: #107288.

@ligorx

ligorx commented Sep 10, 2026

Copy link
Copy Markdown
Author

Clean-rebuild confirmation: I rebuilt the desktop app from this patched source (electron-builder via hermes desktop --build-only) and the fresh bundle carries the function-scoped map (function ...(){return{__HERMES_PLUGIN_SDK__:...}}) instead of a module-init literal. The app boots with both runtime plugins loaded — no runtime load failed lines in the boot log, status-bar chips present.

@kshitijk4poor

Copy link
Copy Markdown
Contributor

Closing as a duplicate of #107303 (@g3org3yo, merged as 6c3d4a4 on 2026-09-10), which lands the same fix — apps/desktop/src/sdk/runtime.ts resolves the plugin SDK namespaces at call time via pluginNamespaces() instead of a module-init GLOBALS snapshot. Current main already carries it, and this branch now conflicts on that block.

Thanks for the independent diagnosis and the Windows packaged-build confirmation — the issue was real and the approach matched what merged. Credit for the fix goes to the earliest submitter per repo policy; if a follow-up gap surfaces in production builds, please open a fresh PR against current main.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/desktop Electron desktop app (apps/desktop/*) comp/plugins Plugin system and bundled plugins duplicate This issue or pull request already exists P1 High — major feature broken, no workaround type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants