{"record":{"id":"d8402c9b2ea37d9b","repo":"neoclide/coc.nvim","slug":"esm-import-of-native-addon-resolved-filename-is","errorCode":null,"errorMessage":"ESM import of native addon ${resolved.filename} is not supported","messagePattern":"ESM import of native addon (.+?) is not supported","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/extension/esm.ts","lineNumber":241,"sourceCode":"  return pathToFileURL(tryRealpath(filename)).href\n}\n\n/**\n * Load (and link) one ESM module in the extension runtime.\n */\nexport async function loadESMModule(runtime: ExtensionRuntime, request: string, parentIdentifier: string): Promise<VMModule> {\n  let resolved = resolveExtensionModule(runtime, request, parentIdentifier, 'import')\n  if (resolved.type === 'coc-api') return createCocApiModule(runtime)\n  if (resolved.type === 'builtin') return createBuiltinModule(runtime, resolved.id)\n  switch (resolved.format) {\n    case 'module':\n      return loadSourceTextModule(runtime, resolved.filename)\n    case 'commonjs':\n      return createCommonJSBridgeModule(runtime, resolved.filename)\n    case 'json':\n      return createJsonModule(runtime, resolved.filename)\n    case 'native':\n      throw new Error(`ESM import of native addon ${resolved.filename} is not supported`)\n  }\n}\n\n/**\n * Dynamic `import()` path: load, link and evaluate the target module so its\n * namespace is fully initialized.\n */\nexport async function dynamicImportModule(runtime: ExtensionRuntime, request: string, parentIdentifier: string): Promise<VMModule> {\n  let module = await loadESMModule(runtime, request, parentIdentifier)\n  instantiateModule(module)\n  await module.evaluate()\n  return module\n}\n\n/**\n * Load an ESM file with `vm.SourceTextModule`, caching it before linking so\n * ESM cycles see the partially initialized module.\n */","sourceCodeStart":223,"sourceCodeEnd":259,"githubUrl":"https://github.com/neoclide/coc.nvim/blob/50e974d9692461a69147d5cab146a8d3e439abe4/src/extension/esm.ts#L223-L259","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (package.json of extension)\n\"exports\": { \"import\": \"./native/index.js\" }  // imports better-sqlite3 addon\n// after\n\"exports\": { \"require\": \"./native/index.cjs\" } // CJS entry require()s the addon","handlingStrategy":"fallback","validationCode":"import { isBuiltin } from 'module'\nimport path from 'path'\nfunction isNativeAddon(resolved: string): boolean {\n  return path.extname(resolved) === '.node'\n}\n// avoid the ESM path when isNativeAddon(resolved.filename) is true; require() it via CJS instead","typeGuard":null,"tryCatchPattern":"try {\n  ns = await loadESMModule(runtime, resolved)\n} catch (e) {\n  if (e.message.includes('native addon')) {\n    ns = createRequire(import.meta.url)(resolved.filename) // CJS bridge for native addons\n  } else throw e\n}","preventionTips":["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."],"tags":["esm","native-addon","nodejs","limitation"],"backgroundTag":"native-module-esm-unsupported","analyzedSha":"50e974d9692461a69147d5cab146a8d3e439abe4","analyzedAt":"2026-08-31T11:17:23.966Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}