swc-project/swc · error · TypeError

Cannot destructure ${o}

Error message

Cannot destructure ${o}

What it means

When SWC's ES2015 destructuring transform lowers object patterns, it inserts `_object_destructuring_empty(o)` to reproduce the native check: destructuring an object pattern from `null` or `undefined` must throw. The helper throws `Cannot destructure <value>` (e.g. `Cannot destructure null`) exactly where native engines would.

Source

Thrown at crates/swc_ecma_transforms_base/src/helpers/generated/_object_destructuring_empty.rs:11

// This file is generated by `cargo codegen helpers`. DO NOT MODIFY.

use super::{HelperDef, HelperName};

pub const DEF: HelperDef = HelperDef {
    name: HelperName::object_destructuring_empty,
    local: "_object_destructuring_empty",
    import_path: "@swc/helpers/_/_object_destructuring_empty",
    #[cfg(feature = "inline-helpers")]
    source: r#"function _object_destructuring_empty(o) {
    if (o === null || o === void 0) throw new TypeError("Cannot destructure " + o);

    return o;
}
"#,
    #[cfg(feature = "inline-helpers")]
    deps: super::HelperBitmap::from_bits(0x00000000000000100000000000000000),
};

#[cfg(feature = "inline-helpers")]
pub fn stmts() -> &'static [swc_ecma_ast::Stmt] {
    static STMTS: once_cell::sync::Lazy<Vec<swc_ecma_ast::Stmt>> =
        once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path));
    &STMTS
}

View on GitHub (pinned to 5176682b65)

Solutions

  1. Give the parameter a default: `function f({ a } = {}) { ... }`.
  2. Coalesce at the boundary: `const { a } = resp ?? {};` or `const { a } = resp || {};`.
  3. Add an early guard: `if (!resp) return;` before destructuring.
  4. Fix the caller to always pass an object.

Example fix

// before
function render({ theme }) {}
// called with no argument -> TypeError: Cannot destructure undefined
// after
function render({ theme } = {}) {}
Defensive patterns

Strategy: validation

Validate before calling

// Null-check before object destructuring, or default the pattern at the boundary.
function render(options) {
  if (options == null) options = {};
  const { theme, layout } = options; // safe now
}
// or: const { theme, layout } = options ?? {};

Type guard

const isNonNullObject = (v: unknown): v is Record<string, unknown> =>
  typeof v === 'object' && v !== null;

Try / catch

try {
  const { a } = resp;
} catch (err) {
  if (err instanceof TypeError && /^Cannot destructure/.test(err.message)) {
    // resp was null/undefined — retry with a default shape
    const { a = null } = {};
  } else throw err;
}

Prevention

When it happens

Trigger: `const { a } = v` (including empty pattern `const {} = v` and defaulted nested patterns) where `v` is `null` or `undefined`; also `function f({ a }) {}` invoked as `f()` — the undefined argument is destructured.

Common situations: A config object parameter not passed by a caller; `JSON.parse` returning `null`; an API field becoming nullable; refactoring positional arguments into an options object while some call sites were missed.

Related errors


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