facebook/relay · warning
useRefetchableFragmentNode: Unexpected action type
Error message
useRefetchableFragmentNode: Unexpected action type
What it means
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.
Source
Thrown at packages/react-relay/relay-hooks/legacy/useRefetchableFragmentNode.js:160
onComplete: action.onComplete,
refetchEnvironment: action.refetchEnvironment,
refetchQuery: action.refetchQuery,
renderPolicy: action.renderPolicy,
};
}
case 'reset': {
return {
fetchPolicy: undefined,
mirroredEnvironment: action.environment,
mirroredFragmentIdentifier: action.fragmentIdentifier,
onComplete: undefined,
refetchQuery: null,
renderPolicy: undefined,
};
}
default: {
action.type as empty;
throw new Error('useRefetchableFragmentNode: Unexpected action type');
}
}
}
hook useRefetchableFragmentNode<
TQuery extends OperationType,
TKey extends ?{readonly $data?: unknown, ...},
>(
fragmentNode: ReaderFragment,
parentFragmentRef: unknown,
componentDisplayName: string,
): ReturnType<TQuery, TKey, InternalOptions> {
const parentEnvironment = useRelayEnvironment();
const {refetchableRequest, fragmentRefPathInResponse} = getRefetchMetadata(
fragmentNode,
componentDisplayName,
);
const fragmentIdentifier = getFragmentIdentifier(View on GitHub (pinned to 668b1b85e0)
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
Example fix
// before (partial upgrade) "react-relay": "^14.0.0", "relay-runtime": "^13.2.0" // after "react-relay": "14.0.0", "relay-runtime": "14.0.0"
Defensive patterns
Strategy: try-catch
Validate before calling
// Before rendering, verify relay package versions match:
const reactRelayPkg = require('react-relay/package.json');
const runtimePkg = require('relay-runtime/package.json');
if (reactRelayPkg.version !== runtimePkg.version) {
throw new Error(`relay version mismatch: react-relay ${reactRelayPkg.version} vs relay-runtime ${runtimePkg.version}`);
} Type guard
const isKnownRefetchAction = (action) => action != null && ['refetch', 'reset'].includes(action.type); // keep in sync with the hook's handled types
Try / catch
import { ErrorBoundary } from 'react-error-boundary';
<ErrorBoundary
fallbackRender={({ error }) =>
String(error.message).includes('useRefetchableFragmentNode: Unexpected action type')
? <FallbackUI />
: <FatalError error={error} />
}
>
<ComponentUsingRefetchableFragment />
</ErrorBoundary>; Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- MatchContainer: Expected `match` value to be an object or nu
- MatchContainer: Invalid 'match' value, expected an object th
- BabelPluginRelay: Expected plugin context to include "types"
- BabelPluginRelay: Expected exactly one definition per graphq
- BabelPluginRelay: Expected a fragment, mutation, query, or s
AI-assisted analysis of facebook/relay@668b1b85e0 (2026-09-02).
Data as JSON: /api/errors/62677d3dae914e6d.
Report an issue: GitHub.