swc-project/swc · error

failed to parse input type

Error message

failed to parse input type

What it means

This panic comes from the `internal_quote` proc macro that powers the `quote!` macro in `swc_ecma_quote`. After parsing the macro input (output type, `as` keyword, source string, vars), it calls `parse_input_type` to parse the string literal as the requested AST type. The `expect("failed to parse input type")` fires when that parse returns an Err: the quoted source is not valid syntax for the requested type, or the output type is one `parse_input_type` does not support (it bails with "Unknown quote type").

Source

Thrown at crates/swc_ecma_quote_macros/src/lib.rs:33

mod ast;
mod builder;
mod ctxt;
mod input;
mod ret_type;

/// Don't invoke this macro directly, use the `quote!` macro from
/// `swc_ecma_quote` instead.
#[proc_macro]
pub fn internal_quote(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let QuoteInput {
        src,
        as_token: _,
        output_type,
        vars,
    } = syn::parse::<QuoteInput>(input).expect("failed to parse input to quote!()");

    let ret_type =
        parse_input_type(&src.value(), &output_type).expect("failed to parse input type");

    let vars = vars.map(|v| v.1);

    let (stmts, vars) = if let Some(vars) = vars {
        prepare_vars(&ret_type, vars)
    } else {
        Default::default()
    };

    let cx = Ctx { vars };

    let expr_for_ast_creation = ret_type.to_code(&cx);

    syn::Expr::Block(ExprBlock {
        attrs: Default::default(),
        label: Default::default(),
        block: Block {
            brace_token: Default::default(),

View on GitHub (pinned to 5176682b65)

Solutions

  1. Check the string literal inside `quote!(T as "...")`: run it through a JS parser (or `node --check`) and fix the syntax error the message context reports.
  2. Confirm the output type is one of the supported ones (Expr, Pat, Stmt, AssignTarget, ModuleItem, or Box/Option wrapping them); for anything else, build the AST manually.
  3. If the snippet is meant to be interpolated with vars, verify the `$(var)*` placeholders do not break the syntax of the surrounding snippet.
  4. Isolate the failing `quote!` invocation by reading the compile error location, since the panic aborts the whole proc-macro expansion.

Example fix

// before
let expr = quote!(Expr as "a +"); // dangling '+', fails to parse

// after
let expr = quote!(Expr as "a + b");
Defensive patterns

Strategy: validation

Validate before calling

// Validate the snippet parses as T before shipping the quote! invocation
fn snippet_parses(src: &str) -> bool {
    use swc_ecma_parser::{lexer::Lexer, Parser, StringInput, Syntax};
    let fm: swc_common::SourceFile =
        swc_common::SourceFile::new(src.into()); // simplified
    let lexer = Lexer::new(
        Syntax::Es(Default::default()),
        Default::default(),
        StringInput::from(&fm),
        None,
    );
    let mut parser = Parser::new_from(lexer);
    parser.parse_expr().is_ok()
}

#[test]
fn quoted_snippets_are_valid() {
    assert!(snippet_parses("a + b"));
    assert!(!snippet_parses("a +"));
}

Prevention

When it happens

Trigger: Writing `quote!(T as "src")` where "src" fails to parse as T with swc_ecma_parser (e.g. `quote!(Expr as "a +")`, a dangling expression), writing multiple statements where only one expression is allowed, requesting an unsupported output type (only Expr, Pat, Stmt, AssignTarget, ModuleItem, plus Box<T>/Option<T> wrappers are handled), or a Box<T>/Option<T> whose inner T is unknown.

Common situations: Authors of swc transforms writing compile-time AST templates with `quote!`; a typo or unfinished snippet inside the quoted string panics at compile time of the consuming crate. Upgrading swc_ecma_parser versions can also make previously-accepted snippets fail to parse.

Understand the failure class

Related errors


AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17). Data as JSON: /api/errors/0f6e058554e6ce8c. Report an issue: GitHub.