{"record":{"id":"a667120c0fddbf7a","repo":"microsoft/TypeScript","slug":"object-not-disposable","errorCode":null,"errorMessage":"Object not disposable.","messagePattern":"Object not disposable\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/compiler/factory/emitHelpers.ts","lineNumber":1398,"sourceCode":"const addDisposableResourceHelper: UnscopedEmitHelper = {\r\n    name: \"typescript:addDisposableResource\",\r\n    importName: \"__addDisposableResource\",\r\n    scoped: false,\r\n    text: `\r\n        var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {\r\n            if (value !== null && value !== void 0) {\r\n                if (typeof value !== \"object\" && typeof value !== \"function\") throw new TypeError(\"Object expected.\");\r\n                var dispose, inner;\r\n                if (async) {\r\n                    if (!Symbol.asyncDispose) throw new TypeError(\"Symbol.asyncDispose is not defined.\");\r\n                    dispose = value[Symbol.asyncDispose];\r\n                }\r\n                if (dispose === void 0) {\r\n                    if (!Symbol.dispose) throw new TypeError(\"Symbol.dispose is not defined.\");\r\n                    dispose = value[Symbol.dispose];\r\n                    if (async) inner = dispose;\r\n                }\r\n                if (typeof dispose !== \"function\") throw new TypeError(\"Object not disposable.\");\r\n                if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };\r\n                env.stack.push({ value: value, dispose: dispose, async: async });\r\n            }\r\n            else if (async) {\r\n                env.stack.push({ async: true });\r\n            }\r\n            return value;\r\n        };`,\r\n};\r\n\r\n/**\r\n * The `s` variable represents two boolean flags from the `DisposeResources` algorithm:\r\n * - `needsAwait` (`1`) — Indicates that an `await using` for a `null` or `undefined` resource was encountered.\r\n * - `hasAwaited` (`2`) — Indicates that the algorithm has performed an Await.\r\n */\r\nconst disposeResourcesHelper: UnscopedEmitHelper = {\r\n    name: \"typescript:disposeResources\",\r\n    importName: \"__disposeResources\",\r","sourceCodeStart":1380,"sourceCodeEnd":1416,"githubUrl":"https://github.com/microsoft/TypeScript/blob/b465fdbfe175304d9b977da137b2c178ae1091d3/src/compiler/factory/emitHelpers.ts#L1380-L1416","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","solutions":["Implement `[Symbol.dispose]()` (sync) or `[Symbol.asyncDispose]()` (async) on the object.","Adapt an existing API with a small wrapper: `{ [Symbol.dispose]() { resource.close(); } }`.","Type the binding as `Disposable`/`AsyncDisposable` so non-disposable objects are rejected at compile time.","Use `null`/`undefined` for the binding when there is nothing to clean up (helper skips it)."],"exampleFix":"// before\nusing conn = { url: \"...\" };                 // no [Symbol.dispose] -> TypeError\n// after\nusing conn = {\n  url: \"...\",\n  [Symbol.dispose]() { /* close socket */ },\n};","handlingStrategy":"validation","validationCode":"function ensureDisposable<T>(v: T): T extends Disposable ? T : never {\n  if (v !== null && v !== undefined && typeof (v as any)[Symbol.dispose] !== \"function\") {\n    throw new TypeError(\"Object not disposable\");\n  }\n  return v as any;\n}","typeGuard":"function isDisposable(v: unknown): v is Disposable {\n  return v !== null && v !== undefined && typeof (v as any)[Symbol.dispose] === \"function\";\n}","tryCatchPattern":null,"preventionTips":["Type `using`/`await using` bindings as `Disposable`/`AsyncDisposable`.","Wrap resources that expose close/dispose methods instead of binding the raw object.","Bind `null`/`undefined` when acquisition failed and there is nothing to release."],"tags":["disposable","using","runtime","emit-helpers"],"backgroundTag":null,"analyzedSha":"b465fdbfe175304d9b977da137b2c178ae1091d3","analyzedAt":"2026-08-12T05:38:42.698Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}