{"record":{"id":"209d109b42010d6e","repo":"swc-project/swc","slug":"using-declarations-can-only-be-used-with-objects-209d10","errorCode":null,"errorMessage":"using declarations can only be used with objects, functions, null, or undefined.","messagePattern":"using declarations can only be used with objects, functions, null, or undefined\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"crates/swc_ecma_transforms_base/src/helpers/mod.rs","lineNumber":624,"sourceCode":"            Default::default(),\n            |_| {\n                enable_helper!(using_ctx);\n                inject_helpers(Mark::new())\n            },\n            \"let _throw = null\",\n            r#\"\n            function _using_ctx() {\n                var _disposeSuppressedError = typeof SuppressedError === \"function\" ? SuppressedError : function(error, suppressed) {\n                    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,","sourceCodeStart":606,"sourceCodeEnd":642,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_ecma_transforms_base/src/helpers/mod.rs#L606-L642","documentation":"This TypeError is thrown at runtime by the _using_ctx helper that SWC injects when lowering `using` / `await using` declarations (explicit resource management) for targets without native support. The helper's using() function validates every bound value with `Object(value) !== value`, rejecting primitives before looking for a dispose method. The error therefore appears when the compiled output executes, not during the SWC transform itself.","triggerScenarios":"Compiling `using x = 42`, `using x = 'str'`, or `await using x = true` (also symbol/bigint) with @swc/core so the helper runs on execution; an API that is statically typed as an object but actually returns a number/string at runtime and is bound with `using`.","commonSituations":"Refactoring try/finally cleanup into `using` where the acquired value is a handle/ID number; test code binding dummy primitive literals; union-typed producers (e.g. number | Connection) consumed directly by `using`.","solutions":["Make the bound value an object or function that implements [Symbol.dispose] (and/or [Symbol.asyncDispose] for `await using`) — have the producer return that wrapper instead of the primitive","Narrow before binding: only reach the `using` declaration when the value is an object, function, null, or undefined (null/undefined are legal no-ops for the helper)","Wrap primitives explicitly: `using guard = { [Symbol.dispose]() { release(handleId); } }`","Target a runtime with native `using` support (Node 20+/recent targets) so SWC emits the native syntax instead of the validating helper"],"exampleFix":"// before\nusing token = acquireToken(); // acquireToken() returns a number -> helper throws\n\n// after\nconst token = acquireToken();\nusing guard = { [Symbol.dispose]() { releaseToken(token); } };","handlingStrategy":"validation","validationCode":"// Run before executing code whose `using` bindings come from external APIs.\nfunction assertUsableUsingValue(value) {\n  if (value != null && Object(value) !== value) {\n    throw new TypeError(\n      `Invalid using value: expected object/function/null/undefined, got ${typeof value}`\n    );\n  }\n}","typeGuard":"type UsingValue = object | ((...args: unknown[]) => unknown) | null | undefined;\nfunction isUsingValue(v: unknown): v is UsingValue {\n  return v == null || typeof v === 'object' || typeof v === 'function';\n}","tryCatchPattern":"try {\n  using res = acquire(); // compiled to the _using_ctx helper\n} catch (e) {\n  if (e instanceof TypeError && /using declarations can only be used with objects/.test(e.message)) {\n    // producer returned a primitive — fix the producer, do not retry\n  }\n  throw e;\n}","preventionTips":["Type resources as interfaces with [Symbol.dispose] so TypeScript rejects primitives at compile time","Never bind primitive handles/IDs directly — wrap them in a disposable object at the API boundary","Execute the transformed output in tests, not just the SWC transform, so helper runtime errors surface in CI"],"tags":["swc","explicit-resource-management","using-declaration","runtime-typeerror","helpers"],"backgroundTag":"using-declaration-invalid-resource","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","contentChangedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}