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
- Convert the offending module to ESM: replace require() with import and module.exports/exports.x with export / export default
- 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
- Check the error's resolvedPath to identify exactly which module is CJS, then trace which import pulled it in
- 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
- Prefer ESM-only dependencies; check package.json exports for "import" conditions
- Add a lint/CI rule banning require()/module.exports in browser-bound source
- Convert legacy scripts when vendoring them into the source tree
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
- TRANSFORM_FAILED
- FILE_TRANSFORM_NOT_SUPPORTED
- files.maxRequestTransforms must be a positive integer
- files.cache must implement the FileStorage interface
- ${optionPath} must be an array
AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27).
Data as JSON: /api/errors/92f0f668cce09148.
Report an issue: GitHub.