swc-project/swc · error · TypeError
Symbol.dispose is not defined.
Error message
Symbol.dispose is not defined.
What it means
The sync path of `_ts_add_disposable_resource` requires `Symbol.dispose`. When the downleveled `using` declaration runs in a runtime without that well-known symbol, the helper throws `TypeError("Symbol.dispose is not defined.")` instead of silently skipping disposal.
Source
Thrown at crates/swc_ecma_transforms_base/src/helpers/generated/_ts_add_disposable_resource.rs:24
name: HelperName::ts_add_disposable_resource,
local: "_ts_add_disposable_resource",
import_path: "@swc/helpers/_/_ts_add_disposable_resource",
#[cfg(feature = "inline-helpers")]
source: r#"function _ts_add_disposable_resource(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);
}
};
}View on GitHub (pinned to 5176682b65)
Solutions
- Polyfill once at startup: `Symbol.dispose ??= Symbol('Symbol.dispose');` and ensure resources define `[Symbol.dispose]` under that key.
- Use a polyfill package for explicit resource management that installs Symbol.dispose and DisposableStack.
- Upgrade the runtime to one shipping Symbol.dispose.
- Fall back to `try/finally` with manual dispose calls on legacy runtimes.
Example fix
// before
using conn = openConnection(); // Node 18: TypeError: Symbol.dispose is not defined.
// after
Symbol.dispose ??= Symbol('Symbol.dispose');
using conn = openConnection(); Defensive patterns
Strategy: fallback
Validate before calling
// Feature-detect and polyfill Symbol.dispose at the entry point.
if (typeof Symbol.dispose === 'undefined') {
Symbol.dispose = Symbol('Symbol.dispose');
// Attach resources under the same key: res[Symbol.dispose] ??= () => res.close();
} Type guard
const supportsDispose = (): boolean => typeof (Symbol as { dispose?: symbol }).dispose === 'symbol'; Try / catch
try {
using res = open();
} catch (err) {
if (err instanceof TypeError && /Symbol.dispose is not defined/.test(err.message)) {
const res = open();
try { /* work */ } finally { res.close(); } // manual disposal fallback
} else throw err;
} Prevention
- Install a `DisposableStack`/explicit-resource-management polyfill package as the first import in the bundle.
- Ensure polyfilled resources and the `using` site share the same symbol instance (same polyfill, same realm).
- Prefer raising the minimum runtime over shipping long-lived polyfills.
When it happens
Trigger: `using x = res;` executed where `Symbol.dispose` is absent (Node < 20, ES2022-era browsers) with output compiled to the TS helper.
Common situations: Same as the async case: modern TS features deployed to older LTS runtimes; edge/serverless runtimes pinned to old V8; assuming the helper brings its own symbol.
Related errors
- Object not disposable.
- Property [Symbol.dispose] is not a function.
- Object expected.
- Symbol.asyncDispose is not defined.
- using declarations can only be used with objects, functions,
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/c4880bea2466ca1e.
Report an issue: GitHub.