microsoft/TypeScript · error · TypeError
Symbol.dispose is not defined.
Error message
Symbol.dispose is not defined.
What it means
Runtime TypeError from `__addDisposableResource`. After the async path (or when not async), if no disposer was found via `Symbol.asyncDispose`, the helper falls back to `Symbol.dispose`; if that symbol is missing it throws. Thrown for both plain `using` and `await using` (as the fallback) when the runtime lacks the symbol.
Source
Thrown at src/compiler/factory/emitHelpers.ts:1394
return typeof state === "function" ? receiver === state : state.has(receiver);
};`,
};
const addDisposableResourceHelper: UnscopedEmitHelper = {
name: "typescript:addDisposableResource",
importName: "__addDisposableResource",
scoped: false,
text: `
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
if (value !== null && value !== void 0) {
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
var dispose, inner;
if (async) {
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
dispose = value[Symbol.asyncDispose];
}
if (dispose === void 0) {
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
dispose = value[Symbol.dispose];
if (async) inner = dispose;
}
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
env.stack.push({ value: value, dispose: dispose, async: async });
}
else if (async) {
env.stack.push({ async: true });
}
return value;
};`,
};
/**
* The `s` variable represents two boolean flags from the `DisposeResources` algorithm:
* - `needsAwait` (`1`) — Indicates that an `await using` for a `null` or `undefined` resource was encountered.
* - `hasAwaited` (`2`) — Indicates that the algorithm has performed an Await.
View on GitHub (pinned to b465fdbfe1)
Solutions
- Polyfill `Symbol.dispose` at app entry (`(Symbol as any).dispose ??= Symbol("Symbol.dispose")`).
- Upgrade the runtime to one that ships `Symbol.dispose`.
- Raise `target` so the helper is not emitted (native `using` on a supporting runtime).
- If both dispose symbols are polyfilled, ensure the polyfill runs before any module that uses `using`.
Example fix
// before: using transpiled on a runtime without Symbol.dispose -> TypeError
// after:
(Symbol as any).dispose ??= Symbol("Symbol.dispose");
using r = openResource(); Defensive patterns
Strategy: validation
Validate before calling
if ((Symbol as any).dispose === undefined) {
(Symbol as any).dispose = Symbol("Symbol.dispose");
} Type guard
function hasDispose(): boolean { return (Symbol as any).dispose !== undefined; } Prevention
- Polyfill `Symbol.dispose` early when downleveling `using`.
- Set `target`/`lib` consistently with the runtimes you ship to.
- Run polyfills before any module body that uses `using`/`await using`.
When it happens
Trigger: `using x = obj` (or `await using` where asyncDispose was absent) compiled with the downlevel helper, run on a runtime without `Symbol.dispose`. Reached before the per-object disposer is read, so even a correct `[Symbol.dispose]` method does not help if the symbol itself is undefined.
Common situations: Old Node.js/browsers; bundles with a low `target`; SSR/edge runtimes that omit the symbol; code that runs in multiple environments where only some are polyfilled.
Related errors
- Symbol.asyncDispose is not defined.
- Object expected.
- Object not disposable.
- Symbol.asyncIterator is not defined.
- Symbol.iterator is not defined.
AI-assisted analysis of microsoft/TypeScript@b465fdbfe1 (2026-08-12).
Data as JSON: /api/errors/02b87beb37521486.
Report an issue: GitHub.