{"record":{"id":"e3ce0325e4ad01a8","repo":"facebook/relay","slug":"expected-to-have-a-reader-operation-for-normal-n","errorCode":null,"errorMessage":"Expected to have a reader operation for `{normal_name}`","messagePattern":"Expected to have a reader operation for `(.+?)`","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler/crates/relay-compiler/src/build_project/generate_artifacts.rs","lineNumber":357,"sourceCode":"\nimpl OperationGroup<'_> {\n    fn new() -> Self {\n        OperationGroup {\n            normalization: None,\n            operation_text: None,\n            reader: None,\n            typegen: None,\n        }\n    }\n\n    fn expect_reader(&self) -> Arc<OperationDefinition> {\n        let normal_name = self\n            .normalization\n            .map_or(\"MISSING_ENTRY\", |n| n.name.item.0.lookup());\n\n        Arc::clone(\n            self.reader.unwrap_or_else(|| {\n                panic!(\"Expected to have a reader operation for `{normal_name}`\")\n            }),\n        )\n    }\n\n    fn expect_typegen(&self) -> Arc<OperationDefinition> {\n        let normal_name = self\n            .normalization\n            .map_or(\"MISSING_ENTRY\", |n| n.name.item.0.lookup());\n\n        Arc::clone(\n            self.typegen.unwrap_or_else(|| {\n                panic!(\"Expected to have a typegen operation for `{normal_name}`\")\n            }),\n        )\n    }\n}\n\n/// Groups operations from the given programs by name for efficient access.","sourceCodeStart":339,"sourceCodeEnd":375,"githubUrl":"https://github.com/facebook/relay/blob/668b1b85e06261aa3b58dabfc51f8b5524a70955/compiler/crates/relay-compiler/src/build_project/generate_artifacts.rs#L339-L375","documentation":"expect_reader unwraps the optional reader operation of an operation group and panics if it is None. An artifact typed as Operation or UpdatableQuery requires a reader AST; its absence means grouping produced an inconsistent entry.","triggerScenarios":"ArtifactContent::Operation or ArtifactContent::UpdatableQuery rendering calls expect_reader on a group where self.reader is None while a normalization AST exists (normal_name is used in the message, or MISSING_ENTRY if absent).","commonSituations":"Relay compiler bug after an upgrade, or an operation whose reader AST was dropped by an earlier transform (e.g. @updatable misconfiguration).","solutions":["Clear generated files and recompile from scratch","Check that @updatable and reader-affecting directives are used per current Relay docs","Create a minimal repro and file a Relay compiler issue with the operation name from the panic message"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Ensure a reader AST exists before rendering the artifact\nif (artifact.reader == null) {\n  throw new Error(`Operation ${artifact.normalization?.name ?? 'MISSING_ENTRY'} lacks a reader AST`);\n}","typeGuard":"fn has_reader(a: &ArtifactContent) -> bool { a.reader.is_some() }","tryCatchPattern":"try {\n  renderArtifact(group);\n} catch (panic) {\n  if (/Expected to have a reader operation/.test(String(panic))) {\n    recompileFromCleanState();\n  } else throw panic;\n}","preventionTips":["Recompile from a clean state after upgrades","Avoid directives/flags that drop reader ASTs in production schemas","Report reproducible panics with the operation name from the message"],"tags":["compiler","rust","panic","codegen","internal-invariant"],"backgroundTag":"compiler-internal-invariant-panic","analyzedSha":"668b1b85e06261aa3b58dabfc51f8b5524a70955","analyzedAt":"2026-09-02T19:57:20.783Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}