{"record":{"id":"d590ba7af02c1d1b","repo":"facebook/react","slug":"407","errorCode":"407","errorMessage":"Missing getServerSnapshot, which is required for server-rendered content. Will revert to client rendering.","messagePattern":"Missing getServerSnapshot, which is required for server-rendered content\\. Will revert to client rendering\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/react-reconciler/src/ReactFiberHooks.js","lineNumber":1660,"sourceCode":"\n    queue.lastRenderedState = newState;\n  }\n  return [newState, dispatch];\n}\n\nfunction mountSyncExternalStore<T>(\n  subscribe: (() => void) => () => void,\n  getSnapshot: () => T,\n  getServerSnapshot?: () => T,\n): T {\n  const fiber = currentlyRenderingFiber;\n  const hook = mountWorkInProgressHook();\n\n  let nextSnapshot;\n  const isHydrating = getIsHydrating();\n  if (isHydrating) {\n    if (getServerSnapshot === undefined) {\n      throw new Error(\n        'Missing getServerSnapshot, which is required for ' +\n          'server-rendered content. Will revert to client rendering.',\n      );\n    }\n    nextSnapshot = getServerSnapshot();\n    if (__DEV__) {\n      if (!didWarnUncachedGetSnapshot) {\n        if (nextSnapshot !== getServerSnapshot()) {\n          console.error(\n            'The result of getServerSnapshot should be cached to avoid an infinite loop',\n          );\n          didWarnUncachedGetSnapshot = true;\n        }\n      }\n    }\n  } else {\n    nextSnapshot = getSnapshot();\n    if (__DEV__) {","sourceCodeStart":1642,"sourceCodeEnd":1678,"githubUrl":"https://github.com/facebook/react/blob/eafeac097ba51e1eab809c07102126bd5f8e5425/packages/react-reconciler/src/ReactFiberHooks.js#L1642-L1678","documentation":"When a component using useSyncExternalStore mounts, React reads a snapshot. If that mount render is hydrating server-rendered HTML (getIsHydrating() true) and no third getServerSnapshot argument was supplied, React cannot reproduce the value the server rendered from, so it throws instead of silently mismatching hydration.","triggerScenarios":"useSyncExternalStore(subscribe, getSnapshot) called with only two arguments during hydration — i.e. the first client render over SSR HTML (Next.js, Remix, react-dom/hydrateRoot).","commonSituations":"Adding a browser-only store subscription (window size, matchMedia, localStorage, third-party stores) to a component that is server-rendered; hydration failures after introducing the hook in an SSR framework; libraries integrating external stores without a server snapshot.","solutions":["Pass a third getServerSnapshot argument returning the stable server-side value, e.g. useSyncExternalStore(subscribe, () => window.innerWidth, () => 0)","Cache the server snapshot (repeat calls must return the same value, or you get the separate uncached-getServerSnapshot warning)","For truly client-only UI, gate rendering behind a mounted flag (useEffect sets state) so hydration never sees the store value","If the store can report its initial value synchronously, reuse getSnapshot as getServerSnapshot only when it is safe to call on the server"],"exampleFix":"// before\nconst scrollY = useSyncExternalStore(\n  subscribeScroll,\n  () => window.scrollY, // throws during hydration: no server snapshot\n);\n\n// after\nconst scrollY = useSyncExternalStore(\n  subscribeScroll,\n  () => window.scrollY,\n  () => 0, // stable server-rendered value\n);","handlingStrategy":"validation","validationCode":"// Wrapper that refuses the 2-argument form in any SSR-capable app\nexport function useSyncExternalStoreSSR<T>(\n  subscribe: () => () => void,\n  getSnapshot: () => T,\n  getServerSnapshot: () => T,\n): T {\n  if (typeof getServerSnapshot !== 'function') {\n    throw new Error('getServerSnapshot is required when hydration is possible');\n  }\n  return React.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n}","typeGuard":"// Type that makes the server snapshot non-optional at every call site\ntype SSRStoreHook = <T>(\n  subscribe: () => () => void,\n  getSnapshot: () => T,\n  getServerSnapshot: () => T, // required, not `?:`\n) => T;","tryCatchPattern":null,"preventionTips":["Always pass the third getServerSnapshot argument when a component can be server-rendered","Return a cached/stable value from getServerSnapshot (constants or memoized) to also avoid the uncached-snapshot warning","For browser-only values, render a constant on the server and update after mount via a mounted flag","Ban the two-argument form in code review for SSR apps"],"tags":["react","hooks","use-sync-external-store","ssr","hydration","external-store"],"backgroundTag":"hydration-mismatch","analyzedSha":"eafeac097ba51e1eab809c07102126bd5f8e5425","analyzedAt":"2026-08-21T22:01:08.818Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}