swc-project/swc · error

illegal conversion: Cannot convert {:?} to ObjectKey - babel

Error message

illegal conversion: Cannot convert {:?} to ObjectKey - babel has no equivalent

What it means

When an expression babelify result is converted into an object key (From<ExprOutput> for ObjectKey, expr.rs:193-206), a PrivateName result panics: Babel's ObjectMember key types (Id/String/Numeric/Expression) have no PrivateName form. Object keys are exactly where a `#x` computed-key misuse surfaces.

Source

Thrown at crates/swc_estree_compat/src/babelify/expr.rs:210

impl From<ExprOutput> for BinaryExprLeft {
    fn from(o: ExprOutput) -> Self {
        match o {
            ExprOutput::Expr(e) => BinaryExprLeft::Expr(e),
            ExprOutput::Private(p) => BinaryExprLeft::Private(p),
        }
    }
}

impl From<ExprOutput> for ObjectKey {
    fn from(o: ExprOutput) -> Self {
        match o {
            ExprOutput::Expr(e) => match *e {
                Expression::Id(i) => ObjectKey::Id(i),
                Expression::Literal(Literal::String(s)) => ObjectKey::String(s),
                Expression::Literal(Literal::Numeric(n)) => ObjectKey::Numeric(n),
                _ => ObjectKey::Expr(e),
            },
            ExprOutput::Private(_) => panic!(
                "illegal conversion: Cannot convert {:?} to ObjectKey - babel has no equivalent",
                &o
            ),
        }
    }
}

impl From<ExprOutput> for MemberExprProp {
    fn from(o: ExprOutput) -> Self {
        match o {
            ExprOutput::Private(p) => MemberExprProp::PrivateName(p),
            ExprOutput::Expr(e) => match *e {
                Expression::Id(i) => MemberExprProp::Id(i),
                _ => MemberExprProp::Expr(e),
            },
        }
    }
}

View on GitHub (pinned to 5176682b65)

Solutions

  1. Use a plain identifier or string for the object key instead of a private name.
  2. Fix the producer that placed a PrivateName into a key position.
  3. Add a pre-scan for PrivateName nodes reaching key conversions.

Example fix

// before
{ [#x]: 1 }

// after
{ ["#x"]: 1 } // or a normal identifier key
Defensive patterns

Strategy: type-guard

Type guard

fn has_private_object_key(program: &Program) -> bool {
    struct Scan(bool);
    impl Visit for Scan {
        fn visit_prop(&mut self, p: &Prop) {
            if let Prop::KeyValue(kv) = p {
                if let PropName::Computed(c) = &kv.key {
                    if matches!(&*c.expr, Expr::PrivateName(_)) { self.0 = true; }
                }
            }
            p.visit_children_with(self);
        }
    }
    let mut s = Scan(false);
    program.visit_with(&mut s);
    s.0
}

Prevention

When it happens

Trigger: Babelifying an AST where a PrivateName was used as an object key — e.g. `{ [#x]: 1 }` from a permissive parser or plugin-built AST (the SWC parser rejects private names there).

Common situations: Plugins copying class member names into object literals; AST fixtures for private members.

Related errors


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