{"record":{"id":"62677d3dae914e6d","repo":"facebook/relay","slug":"userefetchablefragmentnode-unexpected-action-type","errorCode":null,"errorMessage":"useRefetchableFragmentNode: Unexpected action type","messagePattern":"useRefetchableFragmentNode: Unexpected action type","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/react-relay/relay-hooks/legacy/useRefetchableFragmentNode.js","lineNumber":160,"sourceCode":"        onComplete: action.onComplete,\n        refetchEnvironment: action.refetchEnvironment,\n        refetchQuery: action.refetchQuery,\n        renderPolicy: action.renderPolicy,\n      };\n    }\n    case 'reset': {\n      return {\n        fetchPolicy: undefined,\n        mirroredEnvironment: action.environment,\n        mirroredFragmentIdentifier: action.fragmentIdentifier,\n        onComplete: undefined,\n        refetchQuery: null,\n        renderPolicy: undefined,\n      };\n    }\n    default: {\n      action.type as empty;\n      throw new Error('useRefetchableFragmentNode: Unexpected action type');\n    }\n  }\n}\n\nhook useRefetchableFragmentNode<\n  TQuery extends OperationType,\n  TKey extends ?{readonly $data?: unknown, ...},\n>(\n  fragmentNode: ReaderFragment,\n  parentFragmentRef: unknown,\n  componentDisplayName: string,\n): ReturnType<TQuery, TKey, InternalOptions> {\n  const parentEnvironment = useRelayEnvironment();\n  const {refetchableRequest, fragmentRefPathInResponse} = getRefetchMetadata(\n    fragmentNode,\n    componentDisplayName,\n  );\n  const fragmentIdentifier = getFragmentIdentifier(","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/facebook/relay/blob/668b1b85e06261aa3b58dabfc51f8b5524a70955/packages/react-relay/relay-hooks/legacy/useRefetchableFragmentNode.js#L142-L178","documentation":"The internal reducer for useRefetchableFragmentNode switches over known action types and its default branch casts action.type to empty (an exhaustiveness check) and throws. At runtime this means an action with an unrecognized type was dispatched to the hook's internal state machine. Users should never see this; it indicates an internal invariant violation, a version mismatch between relay runtime packages, or corrupted/monkey-patched dispatch.","triggerScenarios":"The reducer receives an action whose type matches none of the handled cases — e.g. mixed relay package versions where one internal module dispatches actions another doesn't know, or custom code reaching into the hook's internals and dispatching a foreign action.","commonSituations":"Mismatched versions of react-relay vs relay-runtime after a partial upgrade; patched/bundled relay code where internal action creators changed; local forks or monkey-patches dispatching custom actions.","solutions":["Align all relay package versions (react-relay, relay-runtime, relay-test-utils) to the same release in package.json/lockfile","Reinstall node_modules and rebuild to clear stale duplicated relay copies","Check for custom middleware/monkey-patching that intercepts or fabricates actions for this hook","If reproducible on matched versions, file an issue with relay with a minimal reproduction"],"exampleFix":"// before (partial upgrade)\n\"react-relay\": \"^14.0.0\",\n\"relay-runtime\": \"^13.2.0\"\n\n// after\n\"react-relay\": \"14.0.0\",\n\"relay-runtime\": \"14.0.0\"","handlingStrategy":"try-catch","validationCode":"// Before rendering, verify relay package versions match:\nconst reactRelayPkg = require('react-relay/package.json');\nconst runtimePkg = require('relay-runtime/package.json');\nif (reactRelayPkg.version !== runtimePkg.version) {\n  throw new Error(`relay version mismatch: react-relay ${reactRelayPkg.version} vs relay-runtime ${runtimePkg.version}`);\n}","typeGuard":"const isKnownRefetchAction = (action) =>\n  action != null && ['refetch', 'reset'].includes(action.type); // keep in sync with the hook's handled types","tryCatchPattern":"import { ErrorBoundary } from 'react-error-boundary';\n<ErrorBoundary\n  fallbackRender={({ error }) =>\n    String(error.message).includes('useRefetchableFragmentNode: Unexpected action type')\n      ? <FallbackUI />\n      : <FatalError error={error} />\n  }\n>\n  <ComponentUsingRefetchableFragment />\n</ErrorBoundary>;","preventionTips":["Keep react-relay and relay-runtime on the exact same version (pin, don't range)","Avoid monkey-patching relay internals or dispatching custom actions into hook reducers","After partial upgrades, clear lockfile and reinstall to eliminate duplicate relay copies"],"tags":["internal","react-relay","relay","runtime","state-machine"],"backgroundTag":"unexpected-action-type","analyzedSha":"668b1b85e06261aa3b58dabfc51f8b5524a70955","analyzedAt":"2026-09-02T19:57:20.783Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}