facebook/react · error · Error

433

433

Error message

useId can only be used while React is rendering

What it means

useId in the Flight server runtime reads a module-level currentRequest that is only set while React is actively rendering a Flight request. The guard throws when useId() runs with no active request, i.e. outside the render pass. It is the server-side equivalent of an invalid hook call.

Source

Thrown at packages/react-server/src/ReactFlightHooks.js:122

};

function unsupportedHook(): void {
  throw new Error('This Hook is not supported in Server Components.');
}

function unsupportedRefresh(): void {
  throw new Error(
    'Refreshing the cache is not supported in Server Components.',
  );
}

function unsupportedContext(): void {
  throw new Error('Cannot read a Client Context from a Server Component.');
}

function useId(): string {
  if (currentRequest === null) {
    throw new Error('useId can only be used while React is rendering');
  }
  const id = currentRequest.identifierCount++;
  // use 'S' for Flight components to distinguish from 'R' and 'r' in Fizz/Client
  return '_' + currentRequest.identifierPrefix + 'S_' + id.toString(32) + '_';
}

function use<T>(usable: Usable<T>): T {
  if (
    // $FlowFixMe[invalid-compare]
    (usable !== null && typeof usable === 'object') ||
    typeof usable === 'function'
  ) {
    // $FlowFixMe[method-unbinding]
    if (typeof usable.then === 'function') {
      // This is a thenable.
      const thenable: Thenable<T> = usable as any;

      // Track the position of the thenable within this fiber.

View on GitHub (pinned to eafeac097b)

Solutions

  1. Call useId() directly in the component body during render and close over the returned value.
  2. If you need an id inside a server action or callback, generate it with crypto.randomUUID() instead.
  3. If the call sits below an await or inside a nested closure, hoist it to the synchronous top level of the component.

Example fix

// before
export default function Page() {
  const save = async () => {
    const id = useId(); // throws: not rendering
    await db.save(id);
  };
  return <Form action={save} />;
}

// after
export default function Page() {
  const id = useId(); // during render
  return <Form action={async () => { await db.save(id); }} />;
}
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Invoking useId() inside a Server Action body, inside a setTimeout/promise callback detached from rendering, at module scope, or from a helper function that runs after the component render has finished.

Common situations: Extracting id generation into a utility invoked lazily; generating ids inside queued/after-render work; calling client-style hooks from code paths that run without the hooks dispatcher installed.

Related errors


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