swc-project/swc · error · TypeError

using declarations can only be used with objects, functions,

Error message

using declarations can only be used with objects, functions, null, or undefined.

What it means

`_using_ctx` bundles a whole scope's `using`/`await using` declarations into a stack with error handling (including a `SuppressedError` fallback). Its inner `using(isAwait, value)` function performs the same spec check as `_using`: primitives are rejected with `TypeError: using declarations can only be used with objects, functions, null, or undefined.`

Source

Thrown at crates/swc_ecma_transforms_base/src/helpers/generated/_using_ctx.rs:26

    import_path: "@swc/helpers/_/_using_ctx",
    #[cfg(feature = "inline-helpers")]
    source: r#"function _using_ctx() {
    var _disposeSuppressedError = typeof SuppressedError === "function"
            // eslint-disable-next-line no-undef
            ? SuppressedError
            : (function(error, suppressed) {
                var err = new Error();
                err.name = "SuppressedError";
                err.suppressed = suppressed;
                err.error = error;
                return err;
            }),
        empty = {},
        stack = [];
    function using(isAwait, value) {
        if (value != null) {
            if (Object(value) !== value) {
                throw new TypeError("using declarations can only be used with objects, functions, null, or undefined.");
            }
            // core-js-pure uses Symbol.for for polyfilling well-known symbols
            if (isAwait) {
                var dispose = value[Symbol.asyncDispose || Symbol.for("Symbol.asyncDispose")];
            }
            if (dispose == null) {
                dispose = value[Symbol.dispose || Symbol.for("Symbol.dispose")];
            }
            if (typeof dispose !== "function") {
                throw new TypeError(`Property [Symbol.dispose] is not a function.`);
            }
            stack.push({ v: value, d: dispose, a: isAwait });
        } else if (isAwait) {
            // provide the nullish `value` as `d` for minification gain
            stack.push({ d: value, a: isAwait });
        }
        return value;
    }

View on GitHub (pinned to 5176682b65)

Solutions

  1. Ensure every resource bound by `using`/`await using` in the block is an object/function or explicitly `null`/`undefined`.
  2. Wrap primitive fallbacks in a disposable adapter object.
  3. Split the primitive resource out of the `using` block into plain `try/finally` handling.
  4. Type the acquire functions' returns as `Disposable | null | undefined` so the compiler catches primitives.

Example fix

// before
{
  using a = getRes();
  using b = tryLock() || 0; // primitive slips in
  // TypeError: using declarations can only be used with objects...
}

// after
{
  using a = getRes();
  const raw = tryLock();
  using b = raw ?? { [Symbol.dispose]: () => {} };
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Validate every resource in the block before entering it (same check as the ctx helper).
const ok = resources.every(
  (r) => r === null || r === undefined || Object(r) === r
);
if (!ok) throw new TypeError('all using resources must be objects/functions/null/undefined');

Type guard

const isUsingCompatible = (v: unknown): v is object | null | undefined =>
  v == null || (typeof v === 'object' || typeof v === 'function');

Prevention

When it happens

Trigger: Any `using` declaration inside a scope that also needs the error/suppression context (multiple resources, try/catch around the block) compiled to `_using_ctx`, where one of the resources evaluates to a primitive (number, string, boolean, symbol, bigint).

Common situations: Mixing several resources in one block where one acquire path returns a primitive fallback (e.g. `using lock = tryAcquire() || 0;`); adopting explicit resource management in bundler output that uses the ctx helper shape.

Related errors


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