swc-project/swc · error · TypeError
Object not disposable.
Error message
Object not disposable.
What it means
After resolving the disposal method from the resource (`value[Symbol.dispose]`, or `value[Symbol.asyncDispose]` for `await using`), `_ts_add_disposable_resource` verifies it is callable. If the resource is an object/function but the resolved method is missing or not a function, it throws `TypeError("Object not disposable.")`.
Source
Thrown at crates/swc_ecma_transforms_base/src/helpers/generated/_ts_add_disposable_resource.rs:32
}
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);
}
};
}
env.stack.push({ value: value, dispose: dispose, async: async });
} else if (async) {
env.stack.push({ async: true });
}
return value;
}
"#,
#[cfg(feature = "inline-helpers")]View on GitHub (pinned to 5176682b65)
Solutions
- Implement the symbol-keyed method: `class Conn { [Symbol.dispose]() { this.close(); } }`.
- If wrapping third-party objects, build a disposable adapter: `{ [Symbol.dispose]: () => obj.close() }`.
- Check `typeof res?.[Symbol.dispose] === 'function'` before the `using` statement.
Example fix
// before
class TempDir { dispose() { rmSync(this.path); } }
using tmp = new TempDir(); // TypeError: Object not disposable.
// after
class TempDir { [Symbol.dispose]() { rmSync(this.path); } }
using tmp = new TempDir(); Defensive patterns
Strategy: type-guard
Validate before calling
// Check disposability before the `using` statement.
const isDisposable = (v, async = false) => {
if (v == null) return true;
if (typeof v !== 'object' && typeof v !== 'function') return false;
const m = v[async ? Symbol.asyncDispose : Symbol.dispose];
return typeof m === 'function';
};
const res = open();
if (!isDisposable(res)) res[Symbol.dispose] = () => res.close(); Type guard
const isDisposable = (v: unknown): v is Disposable => (typeof v === 'object' || typeof v === 'function') && v !== null && typeof (v as Disposable)[Symbol.dispose] === 'function';
Prevention
- Implement `[Symbol.dispose]()` (symbol key, not a string method) on every resource class.
- For third-party objects, attach `obj[Symbol.dispose] ??= () => obj.close()` once at acquisition.
- TypeScript's `Disposable` interface (`using ... : Disposable`) makes missing methods a compile error.
When it happens
Trigger: `using x = {};` or `using x = { [Symbol.dispose]: null };` — any non-null object or function whose `[Symbol.dispose]` (or async variant) is absent or non-callable.
Common situations: Forgetting to implement `[Symbol.dispose]` on a connection/wrapper class; using a string-keyed `dispose()` method instead of the symbol key; a mock/stub resource in tests that lacks the symbol method.
Related errors
- Property [Symbol.dispose] is not a function.
- Object expected.
- Symbol.dispose is not defined.
- using declarations can only be used with objects, functions,
- Property [Symbol.dispose] is not a function.
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/18a3b8a3dfe17ee2.
Report an issue: GitHub.