{"record":{"id":"3e290ca7ff5b4fa9","repo":"facebook/relay","slug":"encountered-an-unexpected-readerselection-variant","errorCode":null,"errorMessage":"Encountered an unexpected ReaderSelection variant in RelayRecordSourceProxy. This indicates a bug in Relay.","messagePattern":"Encountered an unexpected ReaderSelection variant in RelayRecordSourceProxy\\. This indicates a bug in Relay\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/relay-runtime/mutations/createUpdatableProxy.js","lineNumber":190,"sourceCode":"        break;\n      case 'FragmentSpread':\n        // Explicitly ignore\n        break;\n      case 'Condition':\n      case 'ActorChange':\n      case 'InlineDataFragmentSpread':\n      case 'AliasedInlineFragmentSpread':\n      case 'ClientEdgeToClientObject':\n      case 'ClientEdgeToServerObject':\n      case 'Defer':\n      case 'ModuleImport':\n      case 'RequiredField':\n      case 'CatchField':\n      case 'Stream':\n      case 'RelayResolver':\n      case 'RelayLiveResolver':\n        // These types of reader nodes are not currently handled.\n        throw new Error(\n          'Encountered an unexpected ReaderSelection variant in RelayRecordSourceProxy. This indicates a bug in Relay.',\n        );\n      default:\n        selection.kind as empty;\n        throw new Error(\n          'Encountered an unexpected ReaderSelection variant in RelayRecordSourceProxy. This indicates a bug in Relay.',\n        );\n    }\n  }\n}\n\nfunction createSetterForPluralLinkedField(\n  selection: ReaderLinkedField,\n  variables: Variables,\n  updatableProxyRootRecord: RecordProxy,\n  recordSourceProxy: RecordSourceProxy,\n) {\n  return function set(newValue: ReadonlyArray<{__id: string, ...}>) {","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/facebook/relay/blob/668b1b85e06261aa3b58dabfc51f8b5524a70955/packages/relay-runtime/mutations/createUpdatableProxy.js#L172-L208","documentation":"createUpdatableProxy walks reader selections to build updatable proxies for optimistic updates. ReaderSelection kinds like RequiredField, CatchField, Stream, RelayResolver, and RelayLiveResolver are not supported inside updatable mutation proxies; hitting one throws this 'bug in Relay' invariant via the explicit case branch.","triggerScenarios":"Performing an optimistic/updatable mutation whose @required/@catch-wrapped fields, @stream directives, or Relay Resolver / Live Resolver fields fall inside the mutation's updatable selection set.","commonSituations":"Adding @catch or @required directives or a client-side Resolver field to a type that participates in an updatable mutation; migrating a schema to Relay Resolvers while keeping legacy optimistic updates over those fields.","solutions":["Remove or restructure @required/@catch/@stream/Resolver fields from the selection set used by the updatable mutation","Split the mutation so unhandled reader kinds are not part of the updatable region (select plain scalar/object fields only)","Upgrade Relay to a newer version that may support these reader variants in updatable proxies","If nothing above applies, reproduce and file a Relay bug — this path is an internal invariant"],"exampleFix":"// before\nfragment F on User { name @catch { message } }\n// after (updatable fragment)\nfragment F on User { name }","handlingStrategy":"try-catch","validationCode":"// Keep updatable fragments limited to plain fields; detect unsupported directives before compiling mutations\n// e.g. lint rule: fail if @catch/@required/@stream/Resolver fields appear in updatable fragments","typeGuard":null,"tryCatchPattern":"try {\n  commitMutation(env, {mutation, variables, optimisticUpdater: store => {...}});\n} catch (e) {\n  if (e.message.includes('unexpected ReaderSelection variant')) {\n    // retry without the optimistic updater / report the artifact\n  }\n}","preventionTips":["Do not use @catch/@required/@stream or Resolver fields inside updatable mutation fragments","Pin and align relay versions so reader selection kinds are supported","Keep optimistic updaters minimal — prefer optimisticResponse","Add an ErrorBoundary around mutation-triggering UI"],"tags":["optimistic-update","updatable-proxy","relay-resolvers","internal-invariant"],"backgroundTag":"relay-internal-invariant","analyzedSha":"668b1b85e06261aa3b58dabfc51f8b5524a70955","analyzedAt":"2026-09-02T19:57:20.783Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}