neoclide/coc.nvim · error
ESM import of native addon ${resolved.filename} is not suppo
Error message
ESM import of native addon ${resolved.filename} is not supported What it means
loadESMModule resolves an imported module's format and supports source-text, commonjs bridge, and JSON modules. Native addons (.node binaries) cannot be loaded inside a VM SourceTextModule/SyntheticModule, so the 'native' case throws. This is an intentional limitation of the VM-based ESM loader.
Source
Thrown at src/extension/esm.ts:241
return pathToFileURL(tryRealpath(filename)).href
}
/**
* Load (and link) one ESM module in the extension runtime.
*/
export async function loadESMModule(runtime: ExtensionRuntime, request: string, parentIdentifier: string): Promise<VMModule> {
let resolved = resolveExtensionModule(runtime, request, parentIdentifier, 'import')
if (resolved.type === 'coc-api') return createCocApiModule(runtime)
if (resolved.type === 'builtin') return createBuiltinModule(runtime, resolved.id)
switch (resolved.format) {
case 'module':
return loadSourceTextModule(runtime, resolved.filename)
case 'commonjs':
return createCommonJSBridgeModule(runtime, resolved.filename)
case 'json':
return createJsonModule(runtime, resolved.filename)
case 'native':
throw new Error(`ESM import of native addon ${resolved.filename} is not supported`)
}
}
/**
* Dynamic `import()` path: load, link and evaluate the target module so its
* namespace is fully initialized.
*/
export async function dynamicImportModule(runtime: ExtensionRuntime, request: string, parentIdentifier: string): Promise<VMModule> {
let module = await loadESMModule(runtime, request, parentIdentifier)
instantiateModule(module)
await module.evaluate()
return module
}
/**
* Load an ESM file with `vm.SourceTextModule`, caching it before linking so
* ESM cycles see the partially initialized module.
*/View on GitHub (pinned to 50e974d969)
Solutions
- Use the CommonJS loading path for the extension (load it as CJS so native addons load normally).
- Replace the native-addon dependency with a pure-JS or WASM alternative.
- Prebuild/patch the extension so the native module is require()'d from a CJS wrapper.
- File/track an upstream issue; VM-module native loading is not supported by Node's vm API.
Example fix
// before (package.json of extension)
"exports": { "import": "./native/index.js" } // imports better-sqlite3 addon
// after
"exports": { "require": "./native/index.cjs" } // CJS entry require()s the addon Defensive patterns
Strategy: fallback
Validate before calling
import { isBuiltin } from 'module'
import path from 'path'
function isNativeAddon(resolved: string): boolean {
return path.extname(resolved) === '.node'
}
// avoid the ESM path when isNativeAddon(resolved.filename) is true; require() it via CJS instead Try / catch
try {
ns = await loadESMModule(runtime, resolved)
} catch (e) {
if (e.message.includes('native addon')) {
ns = createRequire(import.meta.url)(resolved.filename) // CJS bridge for native addons
} else throw e
} Prevention
- Load extensions containing native addons through the CommonJS path.
- Prefer pure-JS/WASM dependencies in ESM extensions.
- Wrap native addons behind a CJS entry that require()s them.
When it happens
Trigger: An ESM extension (or its dependency graph) does import of a resolved module whose format is 'native' — i.e. a compiled .node addon file reached through loadSourceTextModule or dynamic import paths.
Common situations: Extension depends on packages like better-sqlite3, sharp, or node-gyp addons while loaded via the ESM loader; a dependency's exports map routes the native binary through the import path.
Related errors
- coc.nvim requires Node.js VM modules support for ESM extensi
- Unsupported native addon: ${cacheKey}
- ERR_REQUIRE_ESM
AI-assisted analysis of neoclide/coc.nvim@50e974d969 (2026-08-31).
Data as JSON: /api/errors/d8402c9b2ea37d9b.
Report an issue: GitHub.