solidjs/solid · error · Error
Dispose method must be an explicit argument to createRoot…
Error message
Dispose method must be an explicit argument to createRoot function
What it means
createRoot(fn) called without an owner (unowned) hands fn a dispose callback that, in dev builds, throws when invoked. Unowned roots have no owner to attach disposal to, so Solid makes the useless dispose loud instead of silently doing nothing. In production builds the dispose is simply a no-op.
Solutions
- Pass your own dispose as the second argument: createRoot(disposer => { ... }, myDispose)
- Or run the code inside an existing owner (e.g. inside createRoot created by render())
- Or never call the dispose callback of an unowned root and manage cleanup via onCleanup elsewhere
Example fix
// before
createRoot((dispose) => {
createEffect(() => console.log(state()));
setTimeout(dispose, 1000); // throws in dev
});
// after
const disposer = () => { /* cleanup */ };
createRoot((dispose) => {
createEffect(() => console.log(state()));
// don't call dispose; cleanup handled by disposer
}, disposer); Defensive patterns
Strategy: validation
Validate before calling
let owner: Owner | null = null;
createRoot((dispose) => {
owner = getOwner();
// store dispose only if you provided your own disposer (2nd arg)
}, () => { /* my dispose */ }); Try / catch
try { dispose(); } catch (e) { if (/explicit argument/.test(String(e))) { /* unowned root: no-op intended */ } else throw e; } Prevention
- Never call the dispose argument of an ownerless createRoot
- Pass an explicit disposer as createRoot's 2nd argument when you need custom cleanup
- Create roots inside component/render lifecycles whenever possible
When it happens
Trigger: Calling createRoot(fn) outside of any reactive owner and then invoking the dispose argument passed to fn (e.g. const [dispose] = createRoot(d => ...); dispose()). Common in top-level module code or tests without createRoot's second argument.
Common situations: Setting up module-scope state or web-component internals without an owner; upgrading Solid versions where disposal semantics changed; test setup calling dispose manually.
Related errors
- error handlers created outside a `createRoot` or `render`…
- cleanups created outside a `createRoot` or `render` will…
- computations created outside a `createRoot` or `render`…
- Unexpected type received when initializing 'createMutable'…
- Unexpected type received when initializing 'createStore'…
AI-assisted analysis of solidjs/solid@f47845f9cc (2026-08-27).
Data as JSON: /api/errors/d87ddbedcfb2cd5c.
Report an issue: GitHub.
Appendix: source
Thrown at packages/solid/src/reactive/signal.ts:169
const listener = Listener,
owner = Owner,
unowned = fn.length === 0,
current = detachedOwner === undefined ? owner : detachedOwner,
root: Owner = unowned
? IS_DEV
? { owned: null, cleanups: null, context: null, owner: null }
: UNOWNED
: {
owned: null,
cleanups: null,
context: current ? current.context : null,
owner: current
},
updateFn = unowned
? IS_DEV
? () =>
fn(() => {
throw new Error("Dispose method must be an explicit argument to createRoot function");
})
: fn
: () => fn(() => untrack(() => cleanNode(root)));
if (IS_DEV) DevHooks.afterCreateOwner && DevHooks.afterCreateOwner(root);
Owner = root;
Listener = null;
try {
return runUpdates(updateFn as () => T, true)!;
} finally {
Listener = listener;
Owner = owner;
}
}
export type Accessor<T> = () => T;View on GitHub (pinned to f47845f9cc)