← Back to PRs

#3330: fix(hooks): use pathToFileURL for Windows ESM dynamic import compatibility

by rafaelreis-r open 2026-01-28 13:06 View on GitHub →
## Summary Fixes Windows ESM compatibility in the session-memory hook when dynamically importing the LLM slug generator. ## The Bug On Windows, the dynamic import fails with: ``` Error [ERR_UNSUPPORTED_ESM_URL_SCHEME]: 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. ``` ## Why the Previous Fix (d93f8ffc1) Didn't Work The previous commit correctly fixed the path resolution by using `fileURLToPath(import.meta.url)` instead of the hacky `.replace("file://", "")`. However, it left the dynamic import using a raw filesystem path: ```typescript // After d93f8ffc1 - still broken on Windows const slugGenPath = path.join(moltbotRoot, "llm-slug-generator.js"); const { generateSlugViaLLM } = await import(slugGenPath); // slugGenPath = "C:\Users\...\llm-slug-generator.js" ❌ ``` On Windows, ESM dynamic imports **require** a `file://` URL scheme. A raw Windows path like `C:\foo\bar.js` is not a valid URL and fails. ## The Fix Convert the filesystem path back to a `file://` URL before importing: ```typescript // This commit - works on all platforms const { generateSlugViaLLM } = await import(pathToFileURL(slugGenPath).href); // pathToFileURL converts "C:\Users\..." → "file:///C:/Users/..." ✅ ``` ## Why Both Conversions Are Needed The full flow requires conversions in both directions: | Step | Value | Why | |------|-------|-----| | `import.meta.url` | `file:///C:/Users/.../handler.js` | ESM provides module URL | | `fileURLToPath()` | `C:\Users\...\handler.js` | Needed for `path.resolve()`, `path.join()` | | `path.join()` | `C:\Users\...\llm-slug-generator.js` | Build the target path | | `pathToFileURL()` | `file:///C:/Users/.../llm-slug-generator.js` | Needed for `import()` | This works correctly on all platforms (Unix paths like `/home/...` work with `import()` directly, but using `pathToFileURL` is safe everywhere). ## Testing - Tested on Windows 10 with Node.js 22 - Session-memory hook now successfully imports and runs the LLM slug generator <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR fixes Windows ESM dynamic import compatibility in the bundled `session-memory` hook by converting the computed `llm-slug-generator.js` filesystem path into a `file://` URL before calling `import()`. The hook already needs `fileURLToPath(import.meta.url)` to do path arithmetic; this change completes the round-trip by using `pathToFileURL(slugGenPath).href` so Node’s ESM loader accepts the target on Windows. Change is localized to `src/hooks/bundled/session-memory/handler.ts` and does not affect hook behavior beyond making the slug-generator import work on Windows. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge with minimal risk. - The change is a targeted, correct use of `pathToFileURL()` to satisfy Node’s Windows ESM import requirements, and it does not alter logic outside the dynamic import boundary. - No files require special attention <!-- greptile_other_comments_section --> <sub>(5/5) You can turn off certain types of comments like style [here](https://app.greptile.com/review/github)!</sub> **Context used:** - Context from `dashboard` - CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=fd949e91-5c3a-4ab5-90a1-cbe184fd6ce8)) - Context from `dashboard` - AGENTS.md ([source](https://app.greptile.com/review/custom-context?memory=0d0c8278-ef8e-4d6c-ab21-f5527e322f13)) <!-- /greptile_comment -->

Most Similar PRs