Skip to content

fix(channels): keep bundled dist loads off native Jiti on Windows#62286

Merged
steipete merged 2 commits intoopenclaw:mainfrom
chen-zhang-cs-code:fix-61911-windows-bundled-channel-loader
Apr 7, 2026
Merged

fix(channels): keep bundled dist loads off native Jiti on Windows#62286
steipete merged 2 commits intoopenclaw:mainfrom
chen-zhang-cs-code:fix-61911-windows-bundled-channel-loader

Conversation

@chen-zhang-cs-code
Copy link
Copy Markdown
Contributor

Summary

  • Problem: Windows bundled-channel loads can still hit ERR_UNSUPPORTED_ESM_URL_SCHEME during openclaw onboard / openclaw configure even though shouldPreferNativeJiti() already disables native Jiti on Windows.
  • Why it matters: this is a user-facing regression that blocks first-run setup and channel configuration on native Windows.
  • What changed: keep the bundled channel module loader and bundled entry sidecar loader off Jiti native import for dist/** paths on Windows, and add focused regression tests for both seams.
  • What did NOT change (scope boundary): no plugin manifests, no startup semantics, no global Jiti patching, and no non-Windows loader behavior.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

Root Cause (if applicable)

  • Root cause: two bundled-channel loader seams (src/channels/plugins/module-loader.ts and src/plugin-sdk/channel-entry-contract.ts) re-enabled tryNative for dist/** module paths even on Windows, which bypassed the existing shouldPreferNativeJiti() guard and let Jiti hand raw C:\... paths to native ESM import.
  • Missing detection / guardrail: there was no Windows-specific regression test proving bundled dist/** channel loads stay off native Jiti.
  • Contributing context (if known): the repo already has a Windows-safe path conversion helper in the broader plugin loader, but the bundled channel loaders used a separate dist/** => tryNative shortcut.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/channels/plugins/module-loader.test.ts, src/plugin-sdk/channel-entry-contract.test.ts
  • Scenario the test should lock in: Windows dist/** bundled channel loads and sidecar loads must instantiate Jiti with tryNative: false.
  • Why this is the smallest reliable guardrail: the failure is in loader option selection before channel-specific logic runs, so the narrowest stable test is at the loader seam itself.
  • Existing test that already covers this (if any): None.
  • If no new test is added, why not: N/A

User-visible / Behavior Changes

  • Native Windows users should no longer hit ERR_UNSUPPORTED_ESM_URL_SCHEME from these bundled-channel loader paths during onboarding/configure flows.

Diagram (if applicable)

Before:
[bundled dist loader on Windows] -> [tryNative=true] -> [Jiti native import("C:\\...")] -> [ERR_UNSUPPORTED_ESM_URL_SCHEME]

After:
[bundled dist loader on Windows] -> [tryNative=false] -> [Jiti non-native load path] -> [channel load proceeds]

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No)
  • Data access scope changed? (No)
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: Windows host
  • Runtime/container: Node.js v24.14.0
  • Model/provider: N/A
  • Integration/channel (if any): bundled channel loading during onboarding/configure
  • Relevant config (redacted): N/A

Steps

  1. Mock a Windows host and load a bundled dist/** channel entry through src/channels/plugins/module-loader.ts.
  2. Mock a Windows host and load a bundled dist/** sidecar through src/plugin-sdk/channel-entry-contract.ts.
  3. Assert both seams create Jiti with tryNative: false.

Expected

  • Windows bundled channel loads stay off native Jiti and avoid raw drive-letter native imports.

Actual

  • Focused regression tests now pass.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

  • Verified scenarios: ran pnpm test src/channels/plugins/module-loader.test.ts src/plugin-sdk/channel-entry-contract.test.ts and confirmed the new Windows-specific regression cases pass.
  • Edge cases checked: both the top-level bundled channel loader and bundled entry sidecar loader now keep dist/** loads off native Jiti on Windows.
  • What you did not verify: I did not complete a full interactive native-Windows openclaw onboard / openclaw configure run in this environment.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Migration needed? (No)
  • If yes, exact upgrade steps:

Risks and Mitigations

  • Risk: another Windows loader seam outside bundled channels may still force native Jiti for dist/** paths.
    • Mitigation: scope is intentionally limited to the two seams on the reported onboarding/configure path, and the regression tests pin those exact seams.

Extra Verification Notes

  • pnpm check is currently blocked by unrelated existing extensions/acpx type-resolution errors (Cannot find module 'acpx/dist/runtime.js').
  • The build chain is also blocked in this environment during runtime-postbuild by a Windows symlink EPERM in acpx, after a successful canvas-a2ui bundle step. These failures are outside the touched files.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 7, 2026

Greptile Summary

This PR correctly identifies and fixes the ERR_UNSUPPORTED_ESM_URL_SCHEME root cause in two bundled channel loader seams on Windows: the || modulePath.includes(...) dist-path shortcut overrides shouldPreferNativeJiti()'s already-correct false return on win32, and the added process.platform !== "win32" guard closes that gap for module-loader.ts and channel-entry-contract.ts. The new regression tests are well-structured (per-test vi.doMock/importFreshModule, platform spy, try/finally teardown).

  • Three additional getJiti functions in src/plugins/public-surface-loader.ts, src/plugins/bundled-channel-config-metadata.ts, and src/plugin-sdk/facade-runtime.ts retain the identical unguarded pattern and were explicitly scoped out. Windows users who reach those seams with dist/** module paths will still encounter the same crash."

Confidence Score: 4/5

Safe to merge as a partial fix; three sibling loader seams with the identical bug remain unpatched

The fix is correct and the new tests are well-structured. However three getJiti functions in public-surface-loader.ts, bundled-channel-config-metadata.ts, and facade-runtime.ts retain the unguarded dist-path override, leaving Windows users who reach those seams still exposed to ERR_UNSUPPORTED_ESM_URL_SCHEME.

src/plugins/public-surface-loader.ts (line 73), src/plugins/bundled-channel-config-metadata.ts (line 83), src/plugin-sdk/facade-runtime.ts (line 222)

Comments Outside Diff (1)

  1. src/plugins/public-surface-loader.ts, line 72-73 (link)

    P1 Three sibling loader seams still carry the unguarded dist-path check

    The identical unfixed pattern remains in three other files:

    • src/plugins/public-surface-loader.ts lines 72–73
    • src/plugins/bundled-channel-config-metadata.ts lines 82–83
    • src/plugin-sdk/facade-runtime.ts lines 221–222

    shouldPreferNativeJiti() already returns false on win32, but the || overrides that intent: any dist/** path unconditionally sets tryNative: true, which triggers ERR_UNSUPPORTED_ESM_URL_SCHEME on Windows — the exact root cause this PR fixes in the two reported seams. Windows users who reach these three seams with dist/** module paths will still crash with the same error.

    The same guard applied in the two fixed files should be applied here:

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: src/plugins/public-surface-loader.ts
    Line: 72-73
    
    Comment:
    **Three sibling loader seams still carry the unguarded dist-path check**
    
    The identical unfixed pattern remains in three other files:
    - `src/plugins/public-surface-loader.ts` lines 72–73
    - `src/plugins/bundled-channel-config-metadata.ts` lines 82–83
    - `src/plugin-sdk/facade-runtime.ts` lines 221–222
    
    `shouldPreferNativeJiti()` already returns `false` on `win32`, but the `||` overrides that intent: any `dist/**` path unconditionally sets `tryNative: true`, which triggers `ERR_UNSUPPORTED_ESM_URL_SCHEME` on Windows — the exact root cause this PR fixes in the two reported seams. Windows users who reach these three seams with `dist/**` module paths will still crash with the same error.
    
    The same guard applied in the two fixed files should be applied here:
    
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/plugins/public-surface-loader.ts
Line: 72-73

Comment:
**Three sibling loader seams still carry the unguarded dist-path check**

The identical unfixed pattern remains in three other files:
- `src/plugins/public-surface-loader.ts` lines 72–73
- `src/plugins/bundled-channel-config-metadata.ts` lines 82–83
- `src/plugin-sdk/facade-runtime.ts` lines 221–222

`shouldPreferNativeJiti()` already returns `false` on `win32`, but the `||` overrides that intent: any `dist/**` path unconditionally sets `tryNative: true`, which triggers `ERR_UNSUPPORTED_ESM_URL_SCHEME` on Windows — the exact root cause this PR fixes in the two reported seams. Windows users who reach these three seams with `dist/**` module paths will still crash with the same error.

The same guard applied in the two fixed files should be applied here:
```suggestion
    shouldPreferNativeJiti(modulePath) ||
    (process.platform !== "win32" && modulePath.includes(`${path.sep}dist${path.sep}`));
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix: avoid native Jiti dist loads on Win..." | Re-trigger Greptile

@steipete steipete force-pushed the fix-61911-windows-bundled-channel-loader branch from d724b74 to 15a54b5 Compare April 7, 2026 12:08
@steipete steipete merged commit de3f742 into openclaw:main Apr 7, 2026
9 checks passed
@steipete
Copy link
Copy Markdown
Contributor

steipete commented Apr 7, 2026

Landed via temp rebase onto main.

  • Gate: pnpm check (via committer), pnpm build, pnpm test src/channels/plugins/module-loader.test.ts src/plugin-sdk/channel-entry-contract.test.ts src/plugin-sdk/facade-loader.test.ts src/plugins/public-surface-loader.test.ts src/plugins/sdk-alias.test.ts
  • Base-only failures repro on clean origin/main: pnpm test test/extension-test-boundary.test.ts, pnpm test src/plugins/contracts/boundary-invariants.test.ts
  • Land commit: 15a54b5
  • Merge commit: de3f742

Thanks @chen-zhang-cs-code!

lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

2 participants