{"record":{"id":"34646b54af03fa89","repo":"swc-project/swc","slug":"property-symbol-dispose-is-not-a-function-34646b","errorCode":null,"errorMessage":"Property [Symbol.dispose] is not a function.","messagePattern":"Property \\[Symbol\\.dispose\\] is not a function\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"crates/swc_ecma_transforms_base/src/helpers/mod.rs","lineNumber":633,"sourceCode":"                    var err = new Error();\n                    err.name = \"SuppressedError\";\n                    err.suppressed = suppressed;\n                    err.error = error;\n                    return err;\n                }, empty = {}, stack = [];\n                function using(isAwait, value) {\n                    if (value != null) {\n                        if (Object(value) !== value) {\n                            throw new TypeError(\"using declarations can only be used with objects, functions, null, or undefined.\");\n                        }\n                        if (isAwait) {\n                            var dispose = value[Symbol.asyncDispose || Symbol.for(\"Symbol.asyncDispose\")];\n                        }\n                        if (dispose == null) {\n                            dispose = value[Symbol.dispose || Symbol.for(\"Symbol.dispose\")];\n                        }\n                        if (typeof dispose !== \"function\") {\n                            throw new TypeError(`Property [Symbol.dispose] is not a function.`);\n                        }\n                        stack.push({\n                            v: value,\n                            d: dispose,\n                            a: isAwait\n                        });\n                    } else if (isAwait) {\n                        stack.push({\n                            d: value,\n                            a: isAwait\n                        });\n                    }\n                    return value;\n                }\n                return {\n                    e: empty,\n                    u: using.bind(null, false),\n                    a: using.bind(null, true),","sourceCodeStart":615,"sourceCodeEnd":651,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_ecma_transforms_base/src/helpers/mod.rs#L615-L651","documentation":"Runtime TypeError from the same _using_ctx helper SWC emits for `using` / `await using` lowering. After the value passes the object check, the helper resolves the dispose method — `Symbol.asyncDispose` for `await using`, falling back to `Symbol.dispose` — and requires it to be a function. If the resource has no such well-known method (or a non-function property under that key), the helper throws at the moment the using declaration executes.","triggerScenarios":"`using res = { close() {} }` — cleanup named close/destroy/release/end instead of [Symbol.dispose]; `await using x = obj` where obj defines [Symbol.dispose] as a non-function value; a resource registered under `Symbol.for('Symbol.dispose')` while the runtime has the native Symbol.dispose (the helper's lookup key `Symbol.dispose || Symbol.for(...)` then misses the registration).","commonSituations":"Migrating try/finally DB/stream cleanup to `using` without adapting legacy cleanup APIs; third-party handles exposing .destroy() (sockets) or .release() (locks); polyfill environments where well-known symbol identity differs from Symbol.for registrations.","solutions":["Implement `[Symbol.dispose]()` on the resource class, or `[Symbol.asyncDispose]()` for async-only resources used with `await using`","Adapt legacy resources at the binding site: `using wrapped = { [Symbol.dispose]: () => handle.close() }` (or use TypeScript's DisposableStack)","Remember `await using` accepts a sync [Symbol.dispose] as fallback, but a resource with only async cleanup must expose [Symbol.asyncDispose]","If registering via Symbol.for('Symbol.dispose'), prefer the native Symbol.dispose key when the runtime defines it, so the helper's lookup finds it"],"exampleFix":"// before\nusing handle = getHandle(); // { destroy(): void } -> Property [Symbol.dispose] is not a function.\n\n// after\nconst handle = getHandle();\nusing wrapper = { [Symbol.dispose]: () => handle.destroy() };","handlingStrategy":"type-guard","validationCode":"function assertDisposable(value, { isAwait = false } = {}) {\n  if (value == null) return; // null/undefined are legal no-ops\n  if (Object(value) !== value) return; // handled by the primitive check\n  const method = isAwait\n    ? value[Symbol.asyncDispose] ?? value[Symbol.dispose]\n    : value[Symbol.dispose];\n  if (typeof method !== 'function') {\n    throw new TypeError('Resource bound with `using` has no callable [Symbol.dispose].');\n  }\n}","typeGuard":"interface Disposable { [Symbol.dispose](): void; }\ninterface AsyncDisposable { [Symbol.asyncDispose](): Promise<void>; }\nfunction isDisposable(v: unknown): v is Disposable {\n  return v != null && (typeof v === 'object' || typeof v === 'function')\n    && typeof (v as Disposable)[Symbol.dispose] === 'function';\n}\nfunction isAsyncDisposable(v: unknown): v is AsyncDisposable {\n  return v != null && (typeof v === 'object' || typeof v === 'function')\n    && typeof (v as AsyncDisposable)[Symbol.asyncDispose] === 'function';\n}","tryCatchPattern":"try {\n  using res = acquire();\n} catch (e) {\n  if (e instanceof TypeError && /Symbol\\.dispose\\] is not a function/.test(e.message)) {\n    // resource lacks a dispose method — wrap it before binding, do not retry\n  }\n  throw e;\n}","preventionTips":["Model resources as TS 5.2+ Disposable/AsyncDisposable so the compiler enforces the well-known method","Centralize legacy cleanup adaptation in a wrapDisposable(handle) utility instead of per-callsite objects","For `await using`, verify asyncDispose exists rather than assuming sync dispose is enough"],"tags":["swc","explicit-resource-management","symbol-dispose","runtime-typeerror","helpers"],"backgroundTag":"symbol-dispose-not-a-function","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","contentChangedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}