swc-project/swc · error · anyhow::Error
failed to deserialize program: {}
Error message
failed to deserialize program: {} What it means
Emitted by the build_print_sync wasm macro when the first argument `s` cannot be deserialized into a swc Program. print expects an AST object previously produced by parse - the exact serialized Program shape (type: 'Module'|'Script', span, body, ...) - not source code and not a hand-built JSON tree.
Source
Thrown at crates/binding_macros/src/wasm.rs:253
pub fn print_sync(s: $crate::wasm::JsValue, opts: $crate::wasm::JsValue) -> Result<$crate::wasm::JsValue, $crate::wasm::JsValue> {
use $crate::wasm::PrintArgs;
let c = $crate::wasm::compiler();
$crate::wasm::try_with_handler_globals(
c.cm.clone(),
$opt,
|_handler| {
c.run(|| {
let opts: $crate::wasm::Options = if opts.is_null() || opts.is_undefined() {
Default::default()
} else {
$crate::wasm::serde_wasm_bindgen::from_value(opts)
.map_err(|e| $crate::wasm::anyhow::anyhow!("failed to parse options: {}", e))?
};
let program: $crate::wasm::Program = $crate::wasm::serde_wasm_bindgen::from_value(s)
.map_err(|e| $crate::wasm::anyhow::anyhow!("failed to deserialize program: {}", e))?;
let s = $crate::wasm::anyhow::Context::context(c
.print(
&program,
PrintArgs {
inline_sources_content: true,
source_map: opts.source_maps
.clone()
.unwrap_or($crate::wasm::SourceMapsConfig::Bool(false)),
emit_source_map_columns: opts.config.emit_source_map_columns.into_bool(),
codegen_config: swc_core::ecma::codegen::Config::default()
.with_target(opts.codegen_target().unwrap_or($crate::wasm::EsVersion::Es2020))
.with_minify(opts.config.minify.into()),
..Default::default()
},
),"failed to print code")?;
serde_wasm_bindgen::to_value(&s)
.map_err(|e| anyhow::anyhow!("failed to serialize json: {}", e))View on GitHub (pinned to d7d7434666)
Solutions
- Feed print exactly the value returned by parse/parseSync of the same binding version
- If you must persist ASTs, re-parse the source instead of printing stale AST JSON after upgrading swc
- Do not prune required fields (span, ctxt) when post-processing the AST JSON; check the serde error detail for the missing field name
- Use transform() if your input is source text, not an AST
Example fix
// before: print expects an AST, not source text
printSync('const a = 1;', {});
// after: parse first, then print
const { program } = parseSync('const a = 1;', null);
printSync(program, {}); Defensive patterns
Strategy: type-guard
Validate before calling
// Ensure the value is an AST, not source text, before printing
function assertProgramLike(v) {
if (typeof v === 'string')
throw new TypeError('print expects the AST from parseSync, not source code - use transform() for text input');
if (typeof v !== 'object' || v === null || !('type' in v))
throw new TypeError('print expects a Program object with a type field');
} Type guard
function isProgram(v) {
return typeof v === 'object' && v !== null &&
(v.type === 'Module' || v.type === 'Script') &&
'span' in v && Array.isArray(v.body);
} Try / catch
try {
const out = printSync(program, printOpts);
} catch (e) {
if (String(e).startsWith('failed to deserialize program')) {
// re-parse from source instead of repairing a stale/edited AST
const { program: fresh } = parseSync(src, parseOpts);
return printSync(fresh, printOpts);
}
throw e;
} Prevention
- Only pass values that came from parse/parseSync of the same binding version to print/printSync
- Never persist AST JSON across swc upgrades - store source and re-parse
- Do not strip fields (span, ctxt) when post-processing AST JSON; they are required by deserialization
When it happens
Trigger: Passing raw source code (a JsString/string) to printSync instead of the AST from parseSync; passing an AST serialized by a different swc version whose serialized Program shape drifted; editing/lossy-transforming the AST JSON (dropping required fields like span) before printing; passing arbitrary JSON that happens to have a body array.
Common situations: Misreading the API (print = AST-to-code, transform = code-to-code); round-tripping ASTs through storage and a different swc version on read; trimming AST JSON for size and deleting required fields.
Related errors
- failed to parse options: {}
- failed to serialize json: {}
- Failed to parse the input
- failed to handle: {s}
- failed to handle with unknown panic message
AI-assisted analysis of swc-project/swc@d7d7434666 (2026-08-16).
Data as JSON: /api/errors/20cbabd5f7e63cf4.
Report an issue: GitHub.