swc-project/swc · error
unable to access unknown nodes
Error message
unable to access unknown nodes
What it means
This is the entry point FastDts::transform (crates/swc_typescript/src/fast_dts/mod.rs:87): it dispatches on the Program, handling Program::Module and Program::Script. In builds compiled with `--cfg swc_ast_unknown`, swc_ecma_ast's decoder can yield an `Unknown(tag, value)` top-level program when the serialized payload's node tag is not recognized by this build, and the catch-all arm panics with "unable to access unknown nodes". Hitting this particular site means even the root node is foreign — the whole payload was written by a different swc_ecma_ast version.
Source
Thrown at crates/swc_typescript/src/fast_dts/mod.rs:88
pub fn mark_diagnostic<T: Into<Cow<'static, str>>>(&mut self, message: T, range: Span) {
self.diagnostics.push(DtsIssue {
message: message.into(),
range: SourceRange {
filename: self.filename.clone(),
span: range,
},
})
}
}
impl FastDts {
pub fn transform(&mut self, program: &mut Program) -> Vec<DtsIssue> {
match program {
Program::Module(module) => self.transform_module_body(&mut module.body, false),
Program::Script(script) => self.transform_script(script),
#[cfg(swc_ast_unknown)]
_ => panic!("unable to access unknown nodes"),
}
take(&mut self.diagnostics)
}
fn transform_module_body(
&mut self,
items: &mut Vec<ModuleItem>,
in_global_or_lit_module: bool,
) {
// 1. Analyze usage
self.used_refs.extend(TypeUsageAnalyzer::analyze(
items,
self.internal_annotations.as_ref(),
));
// 2. Transform.
Self::remove_function_overloads_in_module(items);
self.transform_module_items(items);View on GitHub (pinned to 5176682b65)
Solutions
- Pin and align the single swc_core version used by both the AST producer and the swc_typescript consumer; verify with `cargo tree -i swc_ecma_ast` that only one version resolves.
- Upgrade the consumer (swc_typescript/swc_core/@swc/core) to at least the producer's version so the root Program decodes concretely.
- Re-parse from source with the same build's swc_ecma_parser instead of deserializing foreign payloads.
- Version-stamp serialized ASTs and reject/fall back to re-parse when the stamp does not match the current swc_ecma_ast version.
Example fix
// before: blindly decode any payload into a Program
let program: Program = deserialize(bytes)?;
let issues = dts.transform(&mut program);
// after: gate on the payload's swc version before decoding
let header = read_swc_version(&bytes);
if header != current_ast_version() {
return Err(format!("AST payload from {header} cannot feed this build"));
}
let mut program: Program = deserialize(bytes)?;
let issues = dts.transform(&mut program); Defensive patterns
Strategy: validation
Validate before calling
// Gate the deserialization boundary, not the transform:
fn try_decode_program(bytes: &[u8]) -> Result<Program, String> {
let producer = read_embedded_swc_version(bytes)?;
if producer != compiled_ast_version() {
return Err(format!("AST payload from swc {producer} cannot feed this build"));
}
decode(bytes).map_err(|e| e.to_string())
}
// compiled_ast_version(): record env!("CARGO_PKG_VERSION") of swc_ecma_ast at build time. Type guard
#[cfg(swc_ast_unknown)]
fn program_is_known(p: &Program) -> bool {
!matches!(p, Program::Unknown(..))
} Try / catch
use std::panic::{catch_unwind, AssertUnwindSafe};
let issues = catch_unwind(AssertUnwindSafe(|| dts.transform(&mut program)))
.map_err(|p| p.downcast_ref::<&str>().map(|s| s.to_string()).unwrap_or_default())?; Prevention
- Stamp every serialized AST with the producing swc_ecma_ast version and validate it before decode.
- Keep exactly one swc_ecma_ast version in the dependency graph (`cargo tree -i swc_ecma_ast`).
- Re-parse from source as the fallback whenever version metadata is missing or mismatched.
When it happens
Trigger: FastDts::transform is called on a Program deserialized (serde/cbor/plugin boundary) from a payload whose root program representation differs from what this build of swc_ecma_ast defines — e.g. a payload from a newer or incompatible swc release.
Common situations: Swc wasm plugins receive serialized AST from the host (the plugin fixture .cargo/config.toml sets `--cfg=swc_ast_unknown` exactly for this); CI matrix jobs compile with RUSTFLAGS="--cfg swc_ast_unknown" and check cross-version behavior; custom tooling that persists Programs to disk and reloads them after an upgrade.
Related errors
- unable to access unknown nodes
- unable to access unknown nodes
- unable to access unknown nodes
- unable to access unknown nodes
- unable to access unknown nodes
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/5eb6d5330f474ed7.
Report an issue: GitHub.