swc-project/swc · error · TypeError

Duplicated element (${element.key})

Error message

Duplicated element (${element.key})

What it means

This wasm support crate wraps operations in try_with_json_handler: it installs a swc Handler whose emitter collects diagnostics, runs the op, and if the handler saw no errors it unwraps the op result with .expect("it should not fail without emitting errors to handler"). The panic fires only when the inner operation returns Err while emitting nothing to the handler - an invariant violation inside the library (here on the path used by swc_ts_fast_strip / node wasm support), not a user-input parse error.

Source

Thrown at crates/swc_ecma_transforms_base/src/helpers/generated/_decorate.rs:131

        _addElementPlacement(element, placements);
    });
    elements.forEach(function(element) {
        if (!_hasDecorators(element)) return newElements.push(element);
        var elementFinishersExtras = _decorateElement(element, placements);
        newElements.push(elementFinishersExtras.element);
        newElements.push.apply(newElements, elementFinishersExtras.extras);
        finishers.push.apply(finishers, elementFinishersExtras.finishers);
    });
    if (!decorators) return { elements: newElements, finishers: finishers };
    var result = _decorateConstructor(newElements, decorators);
    finishers.push.apply(finishers, result.finishers);
    result.finishers = finishers;

    return result;
}
function _addElementPlacement(element, placements, silent) {
    var keys = placements[element.placement];
    if (!silent && keys.indexOf(element.key) !== -1) throw new TypeError("Duplicated element (" + element.key + ")");
    keys.push(element.key);
}
function _decorateElement(element, placements) {
    var extras = [];
    var finishers = [];
    for (var decorators = element.decorators, i = decorators.length - 1; i >= 0; i--) {
        var keys = placements[element.placement];
        keys.splice(keys.indexOf(element.key), 1);
        var elementObject = _fromElementDescriptor(element);
        var elementFinisherExtras = _toElementFinisherExtras((0, decorators[i])(elementObject) || elementObject);
        element = elementFinisherExtras.element;
        _addElementPlacement(element, placements);
        if (elementFinisherExtras.finisher) finishers.push(elementFinisherExtras.finisher);
        var newExtras = elementFinisherExtras.extras;
        if (newExtras) {
            for (var j = 0; j < newExtras.length; j++) _addElementPlacement(newExtras[j], placements);
            extras.push.apply(extras, newExtras);
        }

View on GitHub (pinned to 5176682b65)

Solutions

  1. Minimize the failing input and check the panic location via the wasm stack trace; confirm it is this expect and not an input syntax error (syntax errors normally come back as JSON diagnostics).
  2. Update to the latest version of the wasm binding - these invariant gaps are treated as bugs and fixed upstream.
  3. Report the issue to the swc repo (SWC_REPO) with the minimized input, binding version, and stack trace.
  4. As a stopgap, catch the JS exception from the wasm call and fall back to a conservative transform for that file.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const result = await transformWasm(source, options);
} catch (e) {
  if (/it should not fail without emitting errors to handler/.test(String(e?.message))) {
    // library invariant violation, not a user-syntax error
    console.error('swc wasm internal error; input saved for bug report:', source);
    throw e;
  }
  throw e; // normal diagnostics arrive as JSON, not this message
}

Prevention

When it happens

Trigger: A code path in the wrapped operation that returns Err (e.g. anyhow::Error from swc_ts_fast_strip::operate or a non-emitting internal error) without calling handler.struct_err/span_err first. Reproducing typically requires the specific input that makes the transform bail early - malformed or edge-case TypeScript that triggers an unlogged internal failure path.

Common situations: Hitting an untested corner of the TypeScript-stripping pipeline (exotic syntax, very large/deep inputs) in an @swc/wasm-based tool; upgrading a wasm binding where a new early-return was added without handler emission; running the wasm build in browser/edge runtimes where an auxiliary error (e.g. allocation) surfaces as a plain Err.

Related errors


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