openclaw - 💡(How to fix) Fix [Bug] Feishu channel crashes on Windows v2026.4.24: jiti tryNative bypasses pathToFileURL, and mirror dist/node_modules missing openclaw package [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#73285Fetched 2026-04-29 06:21:27
View on GitHub
Comments
1
Participants
2
Timeline
2
Reactions
0
Timeline (top)
closed ×1commented ×1

Error Message

Error Messages

  1. After applying Fix 1, observe Cannot find package 'openclaw' error
  • #62374 - ESM URL scheme error report (closed as fixed)

Root Cause

Issue 1: jiti tryNative bypasses pathToFileURL

Previous fixes (v2026.4.7 PR #61832, #62194, #62286) added toSafeImportPath() in src/plugins/loader.ts and disabled tryNative for bundled dist paths on Windows. However, jiti's internal tryNative code path in jiti.cjs still passes raw Windows paths to nativeImport(), bypassing the pathToFileURL() conversion that exists in nativeImportOrRequire().

In jiti.cjs, the tryNative branch:

if(e.opts.tryNative && !e.opts.transformOptions)
  try {
    if(!(t = jitiResolve(e, t, i)) && i.try) return;
    // BUG: e.nativeImport(t) passes raw Windows path, no pathToFileURL conversion
    return e.nativeImport(t).then(...)
  }

While nativeImportOrRequire() has the conversion:

function nativeImportOrRequire(e, t, i) {
  return i && e.nativeImport
    ? e.nativeImport(function(e) {
        return kt && isAbsolute(e) ? pathToFileURL(e) : e  // pathToFileURL conversion HERE
      }(t)).then(...)
    : jitiInteropDefault(e, e.nativeRequire(t))
}

The tryNative fast-path bypasses nativeImportOrRequire() and calls e.nativeImport(t) directly, where t is a resolved absolute Windows path like C:\Users\...\accounts-DJRdWYvk.js.

Why shouldPreferNativeJiti() / tryNative: false guard didn't help: The resolvePluginLoaderJitiTryNative() function in sdk-alias correctly sets tryNative: false for bundled dist paths on Windows. However, when tryNative is true (for non-dist paths or when the guard doesn't apply), the tryNative branch in jiti's CJS code still has the pathToFileURL gap.

Issue 2: Mirror dist/node_modules missing openclaw package

When prepareBundledPluginRuntimeRoot creates a mirror directory under plugin-runtime-deps/openclaw-<version>-<hash>/, the mirror's dist/ directory contains extension files but no node_modules/openclaw package. When tryNative successfully loads a bundled entry module (after the pathToFileURL fix), Node.js ESM resolver tries to resolve bare specifiers like import ... from "openclaw/plugin-sdk/text-runtime", which requires finding the openclaw package in node_modules. Since it doesn't exist in the mirror directory, resolution fails.

Fix Action

Fix / Workaround

Workaround / Fix Applied

Fix for Issue 1: Patch jiti.cjs

Code Example

[feishu] [default] channel exited: Only URLs with a scheme in: file, data, and node are supported by the default ESM loader. On Windows, absolute paths must be valid file:// URLs. Received protocol 'c:'

---

[feishu] [default] channel exited: Cannot find package 'openclaw' imported from ...\plugin-runtime-deps\openclaw-2026.4.24-ce5f2d314190\dist\extensions\feishu\accounts-DJRdWYvk.js

---

if(e.opts.tryNative && !e.opts.transformOptions)
  try {
    if(!(t = jitiResolve(e, t, i)) && i.try) return;
    // BUG: e.nativeImport(t) passes raw Windows path, no pathToFileURL conversion
    return e.nativeImport(t).then(...)
  }

---

function nativeImportOrRequire(e, t, i) {
  return i && e.nativeImport
    ? e.nativeImport(function(e) {
        return kt && isAbsolute(e) ? pathToFileURL(e) : e  // pathToFileURL conversion HERE
      }(t)).then(...)
    : jitiInteropDefault(e, e.nativeRequire(t))
}

---

// Before (buggy):
return e.nativeImport(t).then(i=>(!1===e.opts.moduleCache&&delete e.nativeRequire.cache[t],jitiInteropDefault(e,i)));

// After (fixed):
return e.nativeImport(kt&&isAbsolute(t)?pathToFileURL(t):t).then(i=>(!1===e.opts.moduleCache&&delete e.nativeRequire.cache[t],jitiInteropDefault(e,i)));

---

New-Item -ItemType Junction -Path "<mirror-dist>\node_modules\openclaw" -Target "<original-openclaw-install-path>"
RAW_BUFFERClick to expand / collapse

Bug Report

Feishu channel (and potentially other bundled channels) crash on Windows v2026.4.24 with two distinct but related issues:

  1. jiti tryNative path bypasses pathToFileURL() conversion, passing raw C:\... paths to import()
  2. Mirror dist/node_modules directory lacks openclaw package symlink, causing Cannot find package 'openclaw'

Error Messages

Issue 1 (original):

[feishu] [default] channel exited: Only URLs with a scheme in: file, data, and node are supported by the default ESM loader. On Windows, absolute paths must be valid file:// URLs. Received protocol 'c:'

Issue 2 (after fixing Issue 1):

[feishu] [default] channel exited: Cannot find package 'openclaw' imported from ...\plugin-runtime-deps\openclaw-2026.4.24-ce5f2d314190\dist\extensions\feishu\accounts-DJRdWYvk.js

Environment

  • OpenClaw version: 2026.4.24
  • Node.js: v24.14.0
  • OS: Windows 11 Pro (10.0.22631)
  • Install method: npm install -g openclaw
  • Channel: feishu

Root Cause Analysis

Issue 1: jiti tryNative bypasses pathToFileURL

Previous fixes (v2026.4.7 PR #61832, #62194, #62286) added toSafeImportPath() in src/plugins/loader.ts and disabled tryNative for bundled dist paths on Windows. However, jiti's internal tryNative code path in jiti.cjs still passes raw Windows paths to nativeImport(), bypassing the pathToFileURL() conversion that exists in nativeImportOrRequire().

In jiti.cjs, the tryNative branch:

if(e.opts.tryNative && !e.opts.transformOptions)
  try {
    if(!(t = jitiResolve(e, t, i)) && i.try) return;
    // BUG: e.nativeImport(t) passes raw Windows path, no pathToFileURL conversion
    return e.nativeImport(t).then(...)
  }

While nativeImportOrRequire() has the conversion:

function nativeImportOrRequire(e, t, i) {
  return i && e.nativeImport
    ? e.nativeImport(function(e) {
        return kt && isAbsolute(e) ? pathToFileURL(e) : e  // pathToFileURL conversion HERE
      }(t)).then(...)
    : jitiInteropDefault(e, e.nativeRequire(t))
}

The tryNative fast-path bypasses nativeImportOrRequire() and calls e.nativeImport(t) directly, where t is a resolved absolute Windows path like C:\Users\...\accounts-DJRdWYvk.js.

Why shouldPreferNativeJiti() / tryNative: false guard didn't help: The resolvePluginLoaderJitiTryNative() function in sdk-alias correctly sets tryNative: false for bundled dist paths on Windows. However, when tryNative is true (for non-dist paths or when the guard doesn't apply), the tryNative branch in jiti's CJS code still has the pathToFileURL gap.

Issue 2: Mirror dist/node_modules missing openclaw package

When prepareBundledPluginRuntimeRoot creates a mirror directory under plugin-runtime-deps/openclaw-<version>-<hash>/, the mirror's dist/ directory contains extension files but no node_modules/openclaw package. When tryNative successfully loads a bundled entry module (after the pathToFileURL fix), Node.js ESM resolver tries to resolve bare specifiers like import ... from "openclaw/plugin-sdk/text-runtime", which requires finding the openclaw package in node_modules. Since it doesn't exist in the mirror directory, resolution fails.

Workaround / Fix Applied

Fix for Issue 1: Patch jiti.cjs

In node_modules/jiti/dist/jiti.cjs, change the tryNative branch to convert Windows absolute paths before passing to nativeImport:

// Before (buggy):
return e.nativeImport(t).then(i=>(!1===e.opts.moduleCache&&delete e.nativeRequire.cache[t],jitiInteropDefault(e,i)));

// After (fixed):
return e.nativeImport(kt&&isAbsolute(t)?pathToFileURL(t):t).then(i=>(!1===e.opts.moduleCache&&delete e.nativeRequire.cache[t],jitiInteropDefault(e,i)));

This mirrors the same pathToFileURL() conversion already present in nativeImportOrRequire().

Fix for Issue 2: Create node_modules junction

New-Item -ItemType Junction -Path "<mirror-dist>\node_modules\openclaw" -Target "<original-openclaw-install-path>"

Reproduction Steps

  1. Install OpenClaw v2026.4.24 globally on Windows: npm install -g openclaw
  2. Configure a feishu channel in openclaw.json
  3. Start the gateway: openclaw gateway --port 18789
  4. Observe the feishu channel crash with ERR_UNSUPPORTED_ESM_URL_SCHEME
  5. After applying Fix 1, observe Cannot find package 'openclaw' error
  6. After applying Fix 2, feishu channel starts successfully

Expected Behavior

Bundled channels (feishu, telegram, discord, etc.) should load and start on Windows without ESM URL scheme errors, regardless of installation path or drive letter.

Related Issues

  • #61795 - Original plugin loader ESM fix (closed as fixed in v2026.4.7)
  • #61832 - toSafeImportPath() PR (merged)
  • #62194 - Bundled channel entry contract Windows fix (merged)
  • #62286 - Keep bundled dist loads off native Jiti on Windows (merged)
  • #62374 - ESM URL scheme error report (closed as fixed)
  • #62502 - Non-C drive ESM issue (open)

extent analysis

TL;DR

To fix the Feishu channel crash on Windows, apply a patch to jiti.cjs to convert Windows absolute paths to file URLs and create a junction for the openclaw package in the mirror directory.

Guidance

  • Identify the jiti.cjs file in node_modules/jiti/dist/ and apply the patch to convert Windows absolute paths to file URLs using pathToFileURL().
  • Create a junction for the openclaw package in the mirror directory using PowerShell: New-Item -ItemType Junction -Path "<mirror-dist>\node_modules\openclaw" -Target "<original-openclaw-install-path>"
  • Verify that the Feishu channel starts successfully after applying the fixes.
  • Check the related issues (#61795, #61832, #62194, #62286, #62374, #62502) for additional context and potential further fixes.

Example

The patch for jiti.cjs involves changing the tryNative branch to:

return e.nativeImport(kt && isAbsolute(t) ? pathToFileURL(t) : t).then(i => (!1 === e.opts.moduleCache && delete e.nativeRequire.cache[t], jitiInteropDefault(e, i)));

This mirrors the pathToFileURL() conversion in nativeImportOrRequire().

Notes

The fixes assume that the jiti and openclaw packages are installed correctly, and the openclaw.json configuration is valid. If issues persist, review the related issues and verify the installation and configuration.

Recommendation

Apply the workaround by patching jiti.cjs and creating a junction for the openclaw package, as this addresses the immediate issues and allows the Feishu channel to start successfully.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix [Bug] Feishu channel crashes on Windows v2026.4.24: jiti tryNative bypasses pathToFileURL, and mirror dist/node_modules missing openclaw package [1 comments, 2 participants]