{"record":{"id":"725cbd69e6255127","repo":"swc-project/swc","slug":"property-symbol-dispose-is-not-a-function","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/generated/_using.rs","lineNumber":25,"sourceCode":"    local: \"_using\",\n    import_path: \"@swc/helpers/_/_using\",\n    #[cfg(feature = \"inline-helpers\")]\n    source: r#\"/* @minVersion 7.22.0 */\n\nfunction _using(stack, value, isAwait) {\n    if (value === null || value === void 0) return value;\n    if (Object(value) !== value) {\n        throw new TypeError(\"using declarations can only be used with objects, functions, null, or undefined.\");\n    }\n    // core-js-pure uses Symbol.for for polyfilling well-known symbols\n    if (isAwait) {\n        var dispose = value[Symbol.asyncDispose || Symbol.for(\"Symbol.asyncDispose\")];\n    }\n    if (dispose === null || dispose === void 0) {\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({ v: value, d: dispose, a: isAwait });\n    return value;\n}\n\"#,\n    #[cfg(feature = \"inline-helpers\")]\n    deps: super::HelperBitmap::from_bits(0x00000010000000000000000000000000),\n};\n\n#[cfg(feature = \"inline-helpers\")]\npub fn stmts() -> &'static [swc_ecma_ast::Stmt] {\n    static STMTS: once_cell::sync::Lazy<Vec<swc_ecma_ast::Stmt>> =\n        once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path));\n    &STMTS\n}\n","sourceCodeStart":7,"sourceCodeEnd":41,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_ecma_transforms_base/src/helpers/generated/_using.rs#L7-L41","documentation":"In `_using`, after the resource passes the object check, the helper resolves its disposal method via `value[Symbol.dispose]` (falling back to the `Symbol.for` polyfill key) and requires it to be callable. Otherwise it throws `TypeError: Property [Symbol.dispose] is not a function.`","triggerScenarios":"`using x = someObject;` where `someObject` has no `[Symbol.dispose]` method, or where the property exists but is not callable (null, number, string-keyed `dispose` instead of the symbol key).","commonSituations":"Wrapping third-party resources (DB connections, file handles) that only have a `.close()`/`.dispose()` method; test stubs without the symbol method; assuming `await using`-style async methods satisfy sync `using`.","solutions":["Give the resource a symbol-keyed method: `res[Symbol.dispose] = () => res.close();` before the `using` statement.","Create an adapter object with `[Symbol.dispose]` that delegates to the library's close/release method.","Verify disposability up front: `typeof res[Symbol.dispose] === 'function'`.","On runtimes without `Symbol.dispose`, polyfill the symbol and attach methods under that same key."],"exampleFix":"// before\nusing conn = await db.connect(); // only has conn.close()\n// TypeError: Property [Symbol.dispose] is not a function.\n\n// after\nconst conn = await db.connect();\nusing guarded = Object.create(conn, { [Symbol.dispose]: { value: () => conn.close() } });\n// or: conn[Symbol.dispose] ??= () => conn.close(); using guarded = conn;","handlingStrategy":"type-guard","validationCode":"// Confirm a callable dispose (or asyncDispose) before the using block.\nconst hasDisposeMethod = (v) => {\n  if (v == null) return true;\n  const key = Symbol.dispose || Symbol.for('Symbol.dispose');\n  return typeof v[key] === 'function';\n};\nif (!hasDisposeMethod(res)) res[Symbol.dispose] = () => res.close();","typeGuard":"const isDisposable = (v: unknown): v is Disposable =>\n  v != null &&\n  (typeof v === 'object' || typeof v === 'function') &&\n  typeof (v as Disposable)[Symbol.dispose ?? Symbol.for('Symbol.dispose')] === 'function';","tryCatchPattern":null,"preventionTips":["Use the symbol key `[Symbol.dispose]`, never a string method name, when making wrappers disposable.","Centralize adapter creation (`toDisposable(res, r => r.close())`) so every resource goes through one checked path.","On polyfilled runtimes, register the fallback key consistently via `Symbol.for('Symbol.dispose')`."],"tags":["using-declaration","symbol-dispose","disposable","explicit-resource-management"],"backgroundTag":"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"}