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

  1. Read the diagnostic emitted just before the bail for the exact syntax error position
  2. Point the tool at plain JavaScript, or strip TS/Flow types first with the appropriate pass
  3. During reduction sessions, treat this as 'candidate is invalid' rather than a tool bug
  4. 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

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

Related errors


AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17). Data as JSON: /api/errors/02180d686baaf3d6. Report an issue: GitHub.