swc-project/swc · error · anyhow::Error
{err:?}
Error message
{err:?} What it means
Compile-time error from swc_ecma_quote_macros: the tokens passed to a quote_*! macro could not be parsed as the expected Rust type T (an SWC AST node). The anyhow error wraps the parser's debug-formatted error and the with_context layer adds 'failed to parse input as `<T>`'. It fires during proc-macro expansion, so it breaks the build of the crate using the macro.
Source
Thrown at crates/swc_ecma_quote_macros/src/ret_type.rs:75
fn parse<T>(
input_str: &str,
op: &mut dyn FnMut(&mut Parser<Lexer>) -> PResult<T>,
) -> Result<BoxWrapper, Error>
where
T: ToCode,
{
let cm = Lrc::new(SourceMap::default());
let fm = cm.new_source_file(FileName::Anon.into(), input_str.to_string());
let lexer = Lexer::new(
Default::default(),
EsVersion::Es2020,
StringInput::from(&*fm),
None,
);
let mut parser = Parser::new_from(lexer);
op(&mut parser)
.map_err(|err| anyhow!("{err:?}"))
.with_context(|| format!("failed to parse input as `{}`", type_name::<T>()))
.map(|val| BoxWrapper(Box::new(val)))
}
fn extract_generic<'a>(name: &str, ty: &'a Type) -> Option<&'a Type> {
if let Type::Path(p) = ty {
let last = p.path.segments.last().unwrap();
if !last.arguments.is_empty() && last.ident == name {
match &last.arguments {
PathArguments::AngleBracketed(tps) => {
let arg = tps.args.first().unwrap();
match arg {
GenericArgument::Type(arg) => return Some(arg),
_ => unimplemented!("generic parameter other than type"),
}
}View on GitHub (pinned to d7d7434666)
Solutions
- Make the quoted content exactly one valid instance of the macro's target type (one expression for quote_expr!, one statement for quote_stmt!, ...)
- Wrap multiple items appropriately or split into several macro invocations
- Check the macro name against the content - statements/declarations do not parse as expressions
- Read the {err:?} payload: it names the unexpected token
Example fix
// before: two expressions inside quote_expr! let e = quote_expr!(&ctx, foo() bar()); // after: a single expression let e = quote_expr!(&ctx, foo());
Defensive patterns
Strategy: validation
Validate before calling
// Rust: validate quoted snippets during development with a test
// that expands the macro and asserts it parses
#[test]
fn quoted_snippets_parse() {
let _ = quote_expr!(&ctx, foo() + 1); // compile of the test itself is the validation
let _ = quote_stmt!(&ctx, let x = 1;);
} Prevention
- One macro = one AST node; split multi-node snippets across macros
- Match the macro suffix to content kind (expr/stmt/ident/type) before writing tokens
- CI-compile all crates containing quote macros so drift fails the build early
When it happens
Trigger: Using quote_expr!, quote_stmt!, quote_ident!, quote_type!, etc. with token soup that is not a valid single production of the target AST type - e.g. two expressions where one is expected, statements passed to quote_expr!, reserved words used as identifiers, or TS-only syntax inside a macro targeting an ECMAScript node.
Common situations: Writing transforms that embed JS snippets via quote macros; refactoring a quoted snippet so it is no longer a single valid expression/statement; copy-pasting multiline JS into a macro that expects one node.
Related errors
- generic parameter other than type
- Box() -> T or Box without a type parameter
- Syntax Error
- module string names unimplemented
- module string names unimplemented
AI-assisted analysis of swc-project/swc@d7d7434666 (2026-08-16).
Data as JSON: /api/errors/591daaa4cc970730.
Report an issue: GitHub.