solidjs/solid · warning

error handlers created outside a `createRoot` or `render` wi

Error message

error handlers created outside a `createRoot` or `render` will never be run

What it means

onError registers an error handler on the current reactive Owner. With Owner === null (no createRoot/render in scope), there is nothing to attach to, so the handler would never run; Solid warns in dev instead of failing silently. It is a console warning, not a thrown error.

Source

Thrown at packages/solid/src/reactive/signal.ts:1827

  };
}

type TODO = any;

/**
 * @deprecated since version 1.7.0 and will be removed in next major - use catchError instead
 * onError - run an effect whenever an error is thrown within the context of the child scopes
 * @param fn an error handler that receives the error
 *
 * * If the error is thrown again inside the error handler, it will trigger the next available parent handler
 *
 * @description https://docs.solidjs.com/reference/reactive-utilities/catch-error
 */
export function onError(fn: (err: Error) => void): void {
  ERROR || (ERROR = Symbol("error"));
  if (Owner === null)
    IS_DEV &&
      console.warn("error handlers created outside a `createRoot` or `render` will never be run");
  else if (Owner.context === null || !Owner.context[ERROR]) {
    // terrible de-opt
    Owner.context = { ...Owner.context, [ERROR]: [fn] };
    mutateContext(Owner, ERROR, [fn]);
  } else Owner.context[ERROR].push(fn);
}

function mutateContext(o: Owner, key: symbol, value: any) {
  if (o.owned) {
    for (let i = 0; i < o.owned.length; i++) {
      if (o.owned[i].context === o.context) mutateContext(o.owned[i], key, value);
      if (!o.owned[i].context) {
        o.owned[i].context = o.context;
        mutateContext(o.owned[i], key, value);
      } else if (!o.owned[i].context[key]) {
        o.owned[i].context[key] = value;
        mutateContext(o.owned[i], key, value);
      }

View on GitHub (pinned to f47845f9cc)

Solutions

  1. Move onError inside a component or createRoot so it has an owner
  2. For top-level error handling, wrap the app in createRoot and register onError there
  3. Use ErrorBoundary around subtrees for rendering errors instead of rootless onError

Example fix

// before
onError((err) => log(err)); // module scope: never runs

// after
createRoot((dispose) => {
  onError((err) => log(err));
  render(() => <App />, root);
});
Defensive patterns

Strategy: validation

Validate before calling

import { getOwner } from 'solid-js';
if (getOwner()) onError(fn); else globalErrorHandler = fn;

Type guard

import { getOwner } from 'solid-js';
const hasOwner = (): boolean => getOwner() !== null;

Prevention

When it happens

Trigger: Calling onError(fn) at module scope, in plain event handlers outside the tree, or in scripts run before render(); any onError call where createRoot was never entered.

Common situations: Adding global error handling at app entry before render(); extracting error logic into utils called outside components; testing components without a root.

Related errors


AI-assisted analysis of solidjs/solid@f47845f9cc (2026-08-27). Data as JSON: /api/errors/bef16d9c1f068d8a. Report an issue: GitHub.