swc-project/swc · error
failed to parse a js file as a module
Error message
failed to parse a js file as a module
What it means
dbg-swc's shared parse_js helper parses input strictly as an ECMAScript module (parse_file_as_module with default EsSyntax and no TS config); a fatal parse error first emits its diagnostic through the swc handler, then this generic bail fires. The emitted diagnostic carries the real line/column and message. Because this helper has no TypeScript configuration, .ts input fails here.
Source
Thrown at crates/dbg-swc/src/util/mod.rs:69
let mut errors = Vec::new();
let comments = SingleThreadedComments::default();
let res = parse_file_as_module(
&fm,
Syntax::Es(Default::default()),
EsVersion::latest(),
Some(&comments),
&mut errors,
)
.map_err(|err| HANDLER.with(|handler| err.into_diagnostic(handler).emit()));
for err in errors {
HANDLER.with(|handler| err.into_diagnostic(handler).emit());
}
let mut m = match res {
Ok(v) => v,
Err(()) => bail!("failed to parse a js file as a module"),
};
m.visit_mut_with(&mut resolver(unresolved_mark, top_level_mark, false));
Ok(ModuleRecord {
module: m,
comments,
top_level_mark,
unresolved_mark,
})
}
pub fn print_js(cm: Arc<SourceMap>, m: &Module, minify: bool) -> Result<String> {
let mut buf = Vec::new();
{
let mut wr = Box::new(JsWriter::new(cm.clone(), "\n", &mut buf, None)) as Box<dyn WriteJs>;
if minify {View on GitHub (pinned to 5176682b65)
Solutions
- Read the diagnostic emitted just before the bail for the exact syntax error position
- Point the tool at plain JavaScript, or strip TS/Flow types first with the appropriate pass
- During reduction sessions, treat this as 'candidate is invalid' rather than a tool bug
- Check the file encoding if the diagnostic points at column 0 of line 1
Example fix
# before $ dbg-swc es minifier ... --file ./src/app.ts error: failed to parse a js file as a module # after - strip types first, then run on plain JS $ npx swc cli-strip ./src/app.ts -o ./out/app.js $ dbg-swc es minifier ... --file ./out/app.js
Defensive patterns
Strategy: try-catch
Validate before calling
fn looks_like_plain_js(path: &Path) -> bool {
matches!(
path.extension().and_then(|e| e.to_str()),
Some("js") | Some("jsx") | Some("mjs") | Some("cjs")
)
}
// dbg-swc's parse_js has no TS config - reject .ts/.tsx/.flow inputs up front
assert!(looks_like_plain_js(&input), "parse_js accepts plain ESM JavaScript only"); Try / catch
match parse_js(fm) {
Ok(record) => record,
Err(e) if format!("{e:#}").contains("failed to parse a js file as a module") => {
// diagnostics were already emitted; in reduction runs this means 'candidate invalid'
return Ok(Default::default()); // or mark candidate as not interesting
}
Err(e) => return Err(e),
} Prevention
- Feed only plain ESM JavaScript to dbg-swc commands built on parse_js
- Strip TypeScript/Flow first with the matching SWC pass
- During creduce sessions, treat parse failures on mutated files as the expected filter outcome
When it happens
Trigger: Feeding any dbg-swc subcommand that uses parse_js a file that is not valid plain ESM: TypeScript syntax, Flow annotations, JSON, HTML, or truncated JS from a reduction run.
Common situations: Pointing the tool at .ts/.flow files by accident; creduce-mutated candidates that no longer parse (where this is the expected 'not interesting' outcome); files with BOM/encoding corruption.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Syntax Error
- Expected function or '('
- Expected url or function
- Expected ident (exclude the keywords 'only', 'not', 'and', '
- Expected identifier value
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/02180d686baaf3d6.
Report an issue: GitHub.