swc-project/swc · error · TypeError

Property [Symbol.dispose] is not a function.

Error message

Property [Symbol.dispose] is not a function.

What it means

Inside `_using_ctx`'s `using(isAwait, value)` function, once the resource passes the object check the helper resolves `value[Symbol.dispose]` (with the `Symbol.for` polyfill-key fallback) and requires a function. A missing or non-callable dispose method throws `TypeError: Property [Symbol.dispose] is not a function.`

Source

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

                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;
    }
    return {
        // error
        e: empty,
        // using
        u: using.bind(null, false),
        // await using
        a: using.bind(null, true),
        // dispose
        d: function() {
            var error = this.e;

View on GitHub (pinned to 5176682b65)

Solutions

  1. Attach the symbol method before the block: `res[Symbol.dispose] ??= () => res.release();`.
  2. Wrap the resource in a disposable adapter whose `[Symbol.dispose]` calls the library method.
  3. Polyfill `Symbol.dispose` at startup so resources and helper use the same key.
  4. Pre-check disposability: `typeof res?.[Symbol.dispose] === 'function'`.

Example fix

// before
{
  using pool = createPool(); // createPool exposes .destroy()
  // TypeError: Property [Symbol.dispose] is not a function.
}

// after
const pool = createPool();
pool[Symbol.dispose] ??= () => pool.destroy();
{
  using p = pool;
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Ensure each resource exposes a callable dispose before the block.
const disposeKey = Symbol.dispose || Symbol.for('Symbol.dispose');
for (const r of resources) {
  if (r != null && typeof r[disposeKey] !== 'function') {
    r[disposeKey] = () => r.close();
  }
}

Type guard

const isDisposable = (v: unknown): v is Disposable =>
  v != null &&
  (typeof v === 'object' || typeof v === 'function') &&
  typeof (v as Record<symbol, unknown>)[Symbol.dispose ?? Symbol.for('Symbol.dispose')] === 'function';

Prevention

When it happens

Trigger: A resource in a `using` block (compiled to the ctx helper) that lacks `[Symbol.dispose]` — e.g. it only exposes `.close()`, `.release()`, or a string-keyed `dispose` — or where the symbol-keyed property is set to a non-function.

Common situations: Wrapping connection pools, file descriptors, or mutexes that use library-specific release methods; polyfilled environments where the resource and the helper disagree on which symbol key identifies dispose.

Related errors


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