neoclide/coc.nvim · error

Unsupported module type "${ext}" for ${cacheKey}

Error message

Unsupported module type "${ext}" for ${cacheKey}

What it means

thrown by the sandbox module loader's load() when a module's file extension isn't one it supports (.json, .node, .js, .cjs, empty, .mjs). ESM (.mjs) gets a dedicated error; anything else is outright unsupported in the sandboxed require implementation.

Source

Thrown at src/extension/loader.ts:255

    if (request === 'coc.nvim') return this.runtime.api
    if (this.isBuiltin(request)) return this.loadBuiltin(request)
    let resolved = resolveExtensionModule(this.runtime, request, parent.filename, 'require')
    if (resolved.type === 'file' && resolved.format === 'module') {
      throw requireESMError(resolved.filename)
    }
    // Builtins and coc.nvim are handled above, so resolution always yields a
    // file module here.
    return this.load((resolved as any).filename, parent)
  }

  public load(filename: string, parent?: ExtensionCommonJSModule, isMain = false): unknown {
    const cacheKey = this.normalizeFilename(filename)
    const ext = path.extname(cacheKey).toLowerCase()
    if (ext === '.json') return this.loadJson(cacheKey, parent)
    if (ext === '.node') return this.loadNative(cacheKey, parent)
    if (ext === '.js' || ext === '.cjs' || ext === '') return this.loadJavaScript(cacheKey, parent)
    if (ext === '.mjs') throw requireESMError(cacheKey)
    throw new Error(`Unsupported module type "${ext}" for ${cacheKey}`)
  }

  /**
   * Load a native addon outside the VM. The addon is dlopen'd by Node and its
   * exports are cached in the runtime module cache.
   */
  public loadNative(filename: string, parent?: ExtensionCommonJSModule): unknown {
    const cacheKey = this.normalizeFilename(filename)
    const cached = this.runtime.cjsModules.get(cacheKey)
    if (cached) return cached.exports
    const nodeModule = new Module(cacheKey)
    nodeModule.filename = cacheKey
    nodeModule.paths = Module._nodeModulePaths(path.dirname(cacheKey))
    const nativeLoad = Module._extensions && Module._extensions['.node']
    if (typeof nativeLoad !== 'function') {
      throw new Error(`Unsupported native addon: ${cacheKey}`)
    }
    nativeLoad(nodeModule, cacheKey)

View on GitHub (pinned to 50e974d969)

Solutions

  1. Compile the module to .js/.cjs before requiring it in the extension.
  2. Rename/emit the file with a supported extension (.js, .cjs, .json).
  3. Use the ESM entry (.mjs) only if your loader path supports it — otherwise bundle to CJS.
  4. Don't require non-code assets via require; read them with fs and parse manually (e.g. .wasm via WebAssembly API if exposed).

Example fix

// before
const helper = require('./helper.ts')
// after (compile first)
const helper = require('./helper.js')
Defensive patterns

Strategy: validation

Validate before calling

const ext = path.extname(modulePath).toLowerCase()
const supported = ['.json', '.node', '.js', '.cjs', '.mjs', '']
if (!supported.includes(ext)) throw new Error(`unsupported ext ${ext}; compile to .js first`)

Type guard

function hasSupportedExt(f) { return ['', '.js', '.cjs', '.json', '.node', '.mjs'].includes(path.extname(f).toLowerCase()) }

Try / catch

try { const m = sandboxRequire(p) } catch (e) { if (e.message.startsWith('Unsupported module type')) { /* bundle/compile the module, then retry */ } else { throw e } }

Prevention

When it happens

Trigger: require('.../.ts') or .tsx/.jsx/.wasm/.mts files from an extension; require resolving a file with an unusual extension; tools trying to load WebAssembly via require.

Common situations: Extensions importing TypeScript source directly instead of compiled JS; monorepo code resolving uncompiled assets; attempted require of .wasm or template files.

Related errors


AI-assisted analysis of neoclide/coc.nvim@50e974d969 (2026-08-31). Data as JSON: /api/errors/2724c030370e3a45. Report an issue: GitHub.