swc-project/swc · error

failed to handle: {s}

Error message

failed to handle: {s}

What it means

The napi HTML binding runs every compiler operation inside std::panic::catch_unwind (binding_html_node/src/util.rs `try_with`). When the swc HTML parser/minifier panics with a String payload, the panic is converted into this anyhow error and returned to Node as a pretty error. It means an internal panic, not a normal user-facing diagnostic: the HTML input hit a code path that unwound instead of returning an error.

Source

Thrown at bindings/binding_html_node/src/util.rs:27

    let cm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
    try_with_handler(
        cm.clone(),
        HandlerOpts {
            skip_filename: false,
            ..Default::default()
        },
        |handler| {
            //
            let result =
                std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| op(&cm, handler)));

            let p = match result {
                Ok(v) => return v,
                Err(v) => v,
            };

            if let Some(s) = p.downcast_ref::<String>() {
                Err(anyhow!("failed to handle: {s}"))
            } else if let Some(s) = p.downcast_ref::<&str>() {
                Err(anyhow!("failed to handle: {s}"))
            } else {
                Err(anyhow!("failed to handle with unknown panic message"))
            }
        },
    )
    .map_err(|e| e.to_pretty_error())
}

View on GitHub (pinned to d7d7434666)

Solutions

  1. Read the panic message in {s} - it names the internal assertion/unwrap that failed and usually points at the construct to remove
  2. Reduce the failing HTML to a minimal repro (delete sections until the panic disappears)
  3. Upgrade or pin @swc/html - internal panics are treated as bugs upstream and are fixed across versions
  4. Report the minimal repro to the swc repository (bindings/binding_html_node) if it reproduces on latest
  5. As a stopgap, skip or sanitize the offending document in your pipeline

Example fix

// before: unguarded call in a batch loop
const out = minify(html, opts);

// after: isolate the panicking document
let out;
try {
  out = minify(html, opts);
} catch (e) {
  failures.push({ file, err: String(e) });
  continue;
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const result = minify(html, opts);
} catch (e) {
  // starts with 'failed to handle: ' -> internal panic, not your bug
  if (String(e).includes('failed to handle')) {
    logPanic(file, String(e)); // collect for an upstream report
    return fallbackHtml; // or skip the document
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling minify()/parse/transform APIs of @swc/html (napi) on HTML that triggers an internal panic - malformed markup, deeply nested or pathological structures, foreign content (SVG/MathML edge cases), or a regression in the vendored swc_html_* crate version.

Common situations: Batch-minifying large site corpora where one unusual document panics; after upgrading @swc/html to a version with a parser regression; HTML fragments (not full documents) fed to a code path expecting full documents.

Related errors


AI-assisted analysis of swc-project/swc@d7d7434666 (2026-08-16). Data as JSON: /api/errors/89046b40a1e4bfd8. Report an issue: GitHub.