swc-project/swc · error
failed to handle
Error message
failed to handle: {s} What it means
binding_core_node's try_with_handler runs the swc operation inside catch_unwind so a Rust panic inside the native binding does not abort the Node.js process. If the panic payload is a String (panic!("...{}", x) format), it is downcast and converted into an anyhow error 'failed to handle: <payload>'. The message you see is therefore the original panic text; the underlying cause is a bug or unrecoverable condition inside swc's transform pipeline.
Solutions
- Treat the appended payload as the real error message and search swc's issue tracker for it; if absent, minimize the input and report a bug
- Upgrade or downgrade @swc/core to a version where the panic path is fixed (many panics are patched quickly)
- Wrap the JS call and capture the error so build tooling (webpack/vite/jest) reports it instead of crashing the pipeline
- If the panic comes from your own visitor/plugin code, replace panic!/unwrap with proper error returns
Example fix
// before (js caller)
const out = transformSync(src, opts); // panics inside native code
// after: contain the failure and surface it
try {
const out = transformSync(src, opts);
} catch (e) {
// e.message starts with 'failed to handle: ' + original panic text
throw new Error(`swc transform failed: ${e.message}`);
} Defensive patterns
Strategy: try-catch
Try / catch
try {
const out = transformSync(src, opts);
} catch (e) {
const m = /failed to handle: ([\s\S]*)$/.exec(e.message);
const panicText = m ? m[1] : e.message;
throw new Error(`swc internal failure (${panicText}); check swc issue tracker`);
} Prevention
- Wrap every swc native call in try/catch so panics surface as build errors, not crashes
- Pin @swc/core versions and test upgrades in CI before rolling out
- Minify-then-diff in CI to catch panics on real-world inputs early
When it happens
Trigger: Any swc transform/parse/minify call through @swc/core (native) whose internal code panics with a formatted String message — e.g. an unimplemented syntax path, an invariant violation on unusual AST shapes, or explicit panic! in the invoked code path.
Common situations: Hitting an swc internal bug on exotic input (decorator edge cases, unusual Unicode, deeply nested ASTs); version regressions after upgrading @swc/core; panics surfacing from user plugins or visitors that panic! with format strings.
Related errors
- failed to handle with unknown panic message
- failed to handle
- failed to handle with unknown panic message
- assignment property be removed before generator pass
- attr_to_prop(JSXEmptyExpr)
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/3d3b41b57b2d1324.
Report an issue: GitHub.
Appendix: source
Thrown at bindings/binding_core_node/src/util.rs:55
GLOBALS
.set(&Default::default(), || {
try_with_handler(
cm,
swc_core::base::HandlerOpts {
skip_filename,
..Default::default()
},
|handler| {
//
let result = catch_unwind(AssertUnwindSafe(|| op(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())
}
// This was originally under swc_nodejs_common, but this is not a public
// interface for the custom binary - they should choose own trace initialization
// instead. Will keep as hidden for now until there's proper usecase.
/// Deprecated no-op kept for compatibility with existing binding entrypoints.
pub fn init_default_trace_subscriber() {}
View on GitHub (pinned to 5176682b65)