swc-project/swc · error

swc does not support `PipelinePrimaryTopicReference`

Error message

swc does not support `PipelinePrimaryTopicReference`

What it means

swc_estree_compat converts an ESTree-shaped AST (swc_estree_ast) into SWC's AST via the Swcify trait. PipelinePrimaryTopicReference is the `#` placeholder of the pipeline-operator proposal; swc_ecma_ast has no node for it, so the impl declares `type Output = Never` and panics as a hard stop when swcify reaches such a node. The conversion cannot produce any valid SWC node for this syntax.

Source

Thrown at crates/swc_estree_compat/src/swcify/expr.rs:1122

    fn swcify(self, _: &Context) -> Self::Output {
        panic!("swc does not support bind expressions")
    }
}

impl Swcify for DoExpression {
    type Output = Never;

    fn swcify(self, _: &Context) -> Self::Output {
        panic!("swc does not support do expressions")
    }
}

impl Swcify for PipelinePrimaryTopicReference {
    type Output = Never;

    fn swcify(self, _: &Context) -> Self::Output {
        panic!("swc does not support `PipelinePrimaryTopicReference`")
    }
}

impl Swcify for RecordExpression {
    type Output = Never;

    fn swcify(self, _: &Context) -> Self::Output {
        panic!("swc does not support record expressions")
    }
}

impl Swcify for TupleExpression {
    type Output = Never;

    fn swcify(self, _: &Context) -> Self::Output {
        panic!("swc does not support tuple expressions")
    }
}

View on GitHub (pinned to 5176682b65)

Solutions

  1. Disable the pipeline-operator syntax plugin in the upstream ESTree parser so `#` topic references never reach swcify
  2. Pre-compile the code with @babel/plugin-proposal-pipeline-operator (or equivalent) down to plain calls before converting
  3. Parse the source with swc_ecma_parser directly instead of converting a foreign ESTree AST
  4. If you build the ESTree AST yourself, rewrite PipelinePrimaryTopicReference nodes into a plain identifier bound before the pipeline before calling swcify

Example fix

// before: acorn/babel parse with pipeline syntax, then convert
let swc_expr = estree_expr.swcify(&ctx); // panics: `swc does not support `PipelinePrimaryTopicReference`

// after: lower proposal syntax first (babel), or reject it up front
// babel.config.js: remove "pipelineOperator" from parserOpts.plugin,
// or precompile: x |> f(#)  ->  f(x)
let swc_expr = estree_expr.swcify(&ctx); // ok
Defensive patterns

Strategy: type-guard

Validate before calling

// Walk the ESTree JSON before swcify; reject unsupported proposal nodes.
fn find_unsupported(v: &serde_json::Value, out: &mut Vec<String>) {
    if let Some(t) = v.get("type").and_then(|t| t.as_str()) {
        if is_unsupported_estree_type(t) { out.push(t.to_string()); }
    }
    if let Some(map) = v.as_object() {
        for child in map.values() { find_unsupported(child, out); }
    }
    if let Some(arr) = v.as_array() {
        for child in arr { find_unsupported(child, out); }
    }
}
let mut bad = Vec::new();
find_unsupported(&estree_json, &mut bad);
if !bad.is_empty() { return Err(format!("unsupported ESTree nodes: {bad:?}")); }

Type guard

fn is_unsupported_estree_type(t: &str) -> bool {
    matches!(
        t,
        "PipelinePrimaryTopicReference" | "BindExpression" | "DoExpression"
            | "RecordExpression" | "TupleExpression" | "ModuleExpression"
    )
}

Try / catch

let out = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
    estree_expr.swcify(&ctx)
}));
match out {
    Ok(node) => node,
    Err(payload) => return Err(format!(
        "swcify rejected an unsupported ESTree node: {payload:?}"
    )),
}

Prevention

When it happens

Trigger: Calling `.swcify(ctx)` on an ESTree expression tree that contains a PipelinePrimaryTopicReference node, produced by parsing code like `x |> f(#)` or `# |> f` with the pipeline-operator syntax enabled in the upstream ESTree parser (e.g. @babel/plugin-syntax-pipeline-operator or an acorn plugin).

Common situations: Feeding babel/acorn output into SWC through swc_estree_compat while the source still contains stage-1 pipeline syntax; astexplorer-style tools that round-trip ESTree ASTs; forgetting to lower proposal syntax with babel before conversion.

Related errors


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