microsoft/TypeScript · error · TypeError

Object not disposable.

Error message

Object not disposable.

What it means

Runtime TypeError from `__addDisposableResource`. After the symbol checks, the helper reads the disposer (`value[Symbol.asyncDispose]`/`value[Symbol.dispose]`) and throws if it is not a function. I.e. the value is an object but does not actually implement the disposable protocol for the chosen mode.

Source

Thrown at src/compiler/factory/emitHelpers.ts:1398

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.
 */
const disposeResourcesHelper: UnscopedEmitHelper = {
    name: "typescript:disposeResources",
    importName: "__disposeResources",

View on GitHub (pinned to b465fdbfe1)

Solutions

  1. Implement `[Symbol.dispose]()` (sync) or `[Symbol.asyncDispose]()` (async) on the object.
  2. Adapt an existing API with a small wrapper: `{ [Symbol.dispose]() { resource.close(); } }`.
  3. Type the binding as `Disposable`/`AsyncDisposable` so non-disposable objects are rejected at compile time.
  4. Use `null`/`undefined` for the binding when there is nothing to clean up (helper skips it).

Example fix

// before
using conn = { url: "..." };                 // no [Symbol.dispose] -> TypeError
// after
using conn = {
  url: "...",
  [Symbol.dispose]() { /* close socket */ },
};
Defensive patterns

Strategy: validation

Validate before calling

function ensureDisposable<T>(v: T): T extends Disposable ? T : never {
  if (v !== null && v !== undefined && typeof (v as any)[Symbol.dispose] !== "function") {
    throw new TypeError("Object not disposable");
  }
  return v as any;
}

Type guard

function isDisposable(v: unknown): v is Disposable {
  return v !== null && v !== undefined && typeof (v as any)[Symbol.dispose] === "function";
}

Prevention

When it happens

Trigger: `using x = obj` where `obj` has no `[Symbol.dispose]`, or `await using x = obj` where `obj` has neither `[Symbol.asyncDispose]` nor `[Symbol.dispose]`. Reached after the symbol-existence checks pass, so the runtime supports disposal but the object doesn't participate.

Common situations: Passing a plain config/record object to `using`; third-party resources that expose `close()`/`dispose()` methods but not the well-known symbol; partial wrappers that implement one mode but are used with the other.

Related errors


AI-assisted analysis of microsoft/TypeScript@b465fdbfe1 (2026-08-12). Data as JSON: /api/errors/a667120c0fddbf7a. Report an issue: GitHub.