{"record":{"id":"20cbabd5f7e63cf4","repo":"swc-project/swc","slug":"failed-to-deserialize-program","errorCode":null,"errorMessage":"failed to deserialize program: {}","messagePattern":"failed to deserialize program: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/binding_macros/src/wasm.rs","lineNumber":253,"sourceCode":"    pub fn print_sync(s: $crate::wasm::JsValue, opts: $crate::wasm::JsValue) -> Result<$crate::wasm::JsValue, $crate::wasm::JsValue> {\n      use $crate::wasm::PrintArgs;\n\n      let c = $crate::wasm::compiler();\n\n      $crate::wasm::try_with_handler_globals(\n          c.cm.clone(),\n          $opt,\n          |_handler| {\n              c.run(|| {\n                  let opts: $crate::wasm::Options = if opts.is_null() || opts.is_undefined() {\n                      Default::default()\n                  } else {\n                    $crate::wasm::serde_wasm_bindgen::from_value(opts)\n                      .map_err(|e| $crate::wasm::anyhow::anyhow!(\"failed to parse options: {}\", e))?\n                  };\n\n                  let program: $crate::wasm::Program = $crate::wasm::serde_wasm_bindgen::from_value(s)\n                    .map_err(|e| $crate::wasm::anyhow::anyhow!(\"failed to deserialize program: {}\", e))?;\n                  let s = $crate::wasm::anyhow::Context::context(c\n                    .print(\n                        &program,\n                        PrintArgs {\n                          inline_sources_content: true,\n                          source_map: opts.source_maps\n                              .clone()\n                              .unwrap_or($crate::wasm::SourceMapsConfig::Bool(false)),\n                          emit_source_map_columns: opts.config.emit_source_map_columns.into_bool(),\n                          codegen_config: swc_core::ecma::codegen::Config::default()\n                              .with_target(opts.codegen_target().unwrap_or($crate::wasm::EsVersion::Es2020))\n                              .with_minify(opts.config.minify.into()),\n                          ..Default::default()\n                        },\n                    ),\"failed to print code\")?;\n\n                    serde_wasm_bindgen::to_value(&s)\n                    .map_err(|e| anyhow::anyhow!(\"failed to serialize json: {}\", e))","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/swc-project/swc/blob/d7d74346665e36e692aa07e13d4ee3ee692ee35c/crates/binding_macros/src/wasm.rs#L235-L271","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before: print expects an AST, not source text\nprintSync('const a = 1;', {});\n\n// after: parse first, then print\nconst { program } = parseSync('const a = 1;', null);\nprintSync(program, {});","handlingStrategy":"type-guard","validationCode":"// Ensure the value is an AST, not source text, before printing\nfunction assertProgramLike(v) {\n  if (typeof v === 'string')\n    throw new TypeError('print expects the AST from parseSync, not source code - use transform() for text input');\n  if (typeof v !== 'object' || v === null || !('type' in v))\n    throw new TypeError('print expects a Program object with a type field');\n}","typeGuard":"function isProgram(v) {\n  return typeof v === 'object' && v !== null &&\n    (v.type === 'Module' || v.type === 'Script') &&\n    'span' in v && Array.isArray(v.body);\n}","tryCatchPattern":"try {\n  const out = printSync(program, printOpts);\n} catch (e) {\n  if (String(e).startsWith('failed to deserialize program')) {\n    // re-parse from source instead of repairing a stale/edited AST\n    const { program: fresh } = parseSync(src, parseOpts);\n    return printSync(fresh, printOpts);\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["wasm","print","deserialization","program-ast","api-misuse"],"backgroundTag":null,"analyzedSha":"d7d74346665e36e692aa07e13d4ee3ee692ee35c","analyzedAt":"2026-08-16T12:41:13.160Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}