remix-run/remix · error · AssetServerCompilationError

COMMONJS_NOT_SUPPORTED

COMMONJS_NOT_SUPPORTED

Error message

CommonJS module detected: ${resolvedPath}. This module uses CommonJS (require/module.exports) which is not supported. Please use an ESM-compatible module.

What it means

During transform, the source is scanned with `mayContainCommonJSModuleGlobals` and then definitively checked with `isCommonJS(analysis.rawCode)`. If the module uses CommonJS constructs (require, module.exports, exports.x), the transform refuses it because the ESM-only asset pipeline cannot process it. This surfaces at build/serve time rather than silently producing broken output.

Source

Thrown at packages/assets/src/lib/scripts/transform.ts:254

      define: args.define ?? undefined,
      minify: args.minify,
      loaders: args.loaders,
      moduleUrl: stableUrlPathname,
      sourceMaps: args.sourceMaps ?? undefined,
      target: args.target ?? undefined,
    })

    analysis.unresolvedImports = analysis.unresolvedImports.filter(
      (unresolved) => !args.externalSet.has(getDisplayImportSpecifier(unresolved.specifier)),
    )

    if (mayContainCommonJSModuleGlobals(sourceText) && isCommonJS(analysis.rawCode)) {
      throw createAssetServerCompilationError(
        `CommonJS module detected: ${resolvedPath}. ` +
          `This module uses CommonJS (require/module.exports) which is not supported. ` +
          `Please use an ESM-compatible module.`,
        {
          code: 'COMMONJS_NOT_SUPPORTED',
        },
      )
    }

    let sourceMap = analysis.sourceMap
      ? rewriteSourceMapSources(
          analysis.sourceMap,
          resolvedPath,
          stableUrlPathname,
          args.sourceMapSourcePaths,
          sourceText,
        )
      : null

    return {
      ok: true,
      tracking: {
        trackedFiles,

View on GitHub (pinned to 9696913134)

Solutions

  1. Convert the offending module to ESM: replace require() with import and module.exports/exports.x with export / export default
  2. If it's a third-party dependency, find an ESM build of it or import it via a wrapper that the pipeline can handle, or vendor and convert it
  3. Check the error's resolvedPath to identify exactly which module is CJS, then trace which import pulled it in
  4. Remove dead CJS snippets (e.g. UMD boilerplate) from files you control

Example fix

// before
const path = require('node:path')
module.exports = { helper }

// after
import path from 'node:path'
export { helper }
Defensive patterns

Strategy: validation

Validate before calling

import { mayContainCommonJSModuleGlobals } from './cjs-detect.ts' // or equivalent
if (mayContainCommonJSModuleGlobals(sourceText) && isCommonJS(sourceText)) {
  // exclude or convert this module before transform
}

Type guard

function isEsmSource(source: string): boolean {
  return !(mayContainCommonJSModuleGlobals(source) && isCommonJS(source))
}

Try / catch

catch (e) { if (isAssetServerCompilationError(e) && e.code === 'COMMONJS_NOT_SUPPORTED') { /* convert module to ESM or swap dependency */ } else throw e }

Prevention

When it happens

Trigger: transformModule on a .js/.ts module whose source contains `require(...)`, `module.exports`, `exports.foo = ...` (after a fast pre-check confirms CJS globals are present). Also triggered by transitive files pulled into the module graph that are CommonJS.

Common situations: Importing an npm package that ships CJS into the browser asset graph; legacy scripts copied into the source tree; code gated by `typeof module !== 'undefined'` still matching the heuristic; env-var style configs written in CJS; bundler-less setups that previously tolerated CJS.

Related errors


AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27). Data as JSON: /api/errors/92f0f668cce09148. Report an issue: GitHub.