facebook/react · error · Error

react-cache: read and preload may only be called from within

Error message

react-cache: read and preload may only be called from within a component's render. They are not supported in event handlers or lifecycle methods.

What it means

react-devtools-shared vendors a simplified react-cache whose read()/preload() must read the cache context during component render. On React versions without React.use it reaches into __SECRET_INTERNALS ReactCurrentDispatcher; when that dispatcher is null you are outside a render pass (event handler, effect, lifecycle method), so it throws this rules-of-hooks-style error instead of crashing deeper.

Source

Thrown at packages/react-devtools-shared/src/devtools/cache.js:57

  write(Key, Value): void,
};

let readContext;
if (typeof React.use === 'function') {
  readContext = function (Context: ReactContext<null>) {
    // eslint-disable-next-line react-hooks-published/rules-of-hooks
    return React.use(Context);
  };
} else if (
  typeof (React as any).__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ===
  'object'
) {
  const ReactCurrentDispatcher = (React as any)
    .__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentDispatcher;
  readContext = function (Context: ReactContext<null>) {
    const dispatcher = ReactCurrentDispatcher.current;
    if (dispatcher === null) {
      throw new Error(
        'react-cache: read and preload may only be called from within a ' +
          "component's render. They are not supported in event handlers or " +
          'lifecycle methods.',
      );
    }
    return dispatcher.readContext(Context);
  };
} else {
  throw new Error('react-cache: Unsupported React version');
}

const CacheContext = createContext(null);

type Config = {useWeakMap?: boolean, ...};

const entries: Map<
  Resource<any, any, any>,
  Map<any, any> | WeakMap<any, any>,

View on GitHub (pinned to eafeac097b)

Solutions

  1. Call read()/preload() during component render only.
  2. If you need the value in an event handler, read it during render and close over the result.
  3. Kick off work with preload() from a render/transition, then read() in a component that suspends.

Example fix

// before
function onClick() {
  const data = resource.read(id); // dispatcher is null here
}

// after
function Panel({id}) {
  const data = resource.read(id); // during render
  return <pre>{JSON.stringify(data)}</pre>;
}
Defensive patterns

Strategy: type-guard

Validate before calling

// only readable during render — check before calling from the React <19 fallback path
const dispatcher = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentDispatcher.current;
if (dispatcher != null) {
  dispatcher.readContext(CacheContext);
}

Type guard

function isDuringRender(React) {
  const internals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
  return internals != null && internals.ReactCurrentDispatcher.current !== null;
}

Try / catch

try {
  value = resource.read(input);
} catch (error) {
  if (/may only be called from within a component's render/.test(error.message)) {
    throw new Error('Moved resource.read() out of render — pass the value from a component instead.');
  }
  throw error;
}

Prevention

When it happens

Trigger: Calling resource.read(input) or resource.preload(input) outside of render on a React without React.use — e.g. inside a click handler, useEffect/useLayoutEffect callback, or class lifecycle — so ReactCurrentDispatcher.current is null when readContext runs.

Common situations: DevTools frontend (or a fork of its profiling cache) running on React < 19 where the fallback dispatcher path is active; code moved from a component body into an effect or callback during refactor; Suspense-style cache patterns copied into event-driven code.

Related errors


AI-assisted analysis of facebook/react@eafeac097b (2026-08-21). Data as JSON: /api/errors/bdb91478a626058b. Report an issue: GitHub.