{"record":{"id":"09d3bfd855b5aee9","repo":"facebook/relay","slug":"expected-to-have-a-typegen-operation-for-normal","errorCode":null,"errorMessage":"Expected to have a typegen operation for `{normal_name}`","messagePattern":"Expected to have a typegen operation for `(.+?)`","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler/crates/relay-compiler/src/build_project/generate_artifacts.rs","lineNumber":369,"sourceCode":"        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.\n/// `Programs::operation(name)` does a linear search, so it's more efficient to\n/// group in a batch.\nfn group_operations(programs: &Programs) -> FnvHashMap<StringKey, OperationGroup<'_>> {\n    let mut grouped_operations: FnvHashMap<StringKey, OperationGroup<'_>> = programs\n        .normalization\n        .operations\n        .iter()\n        .map(|normalization_operation| {\n            (\n                normalization_operation.name.item.0,\n                OperationGroup {\n                    normalization: Some(normalization_operation),","sourceCodeStart":351,"sourceCodeEnd":387,"githubUrl":"https://github.com/facebook/relay/blob/668b1b85e06261aa3b58dabfc51f8b5524a70955/compiler/crates/relay-compiler/src/build_project/generate_artifacts.rs#L351-L387","documentation":"expect_typegen unwraps the optional typegen operation and panics if it is None. Every artifact rendered as Operation or UpdatableQuery must have a typegen AST; a missing one indicates inconsistent operation grouping upstream.","triggerScenarios":"ArtifactContent::Operation or ArtifactContent::UpdatableQuery rendering calls expect_typegen on a group where self.typegen is None; the panic message shows the normalization name (or MISSING_ENTRY).","commonSituations":"Compiler bug or stale/incomplete compiler state after a Relay version bump; operations affected by transforms that suppress typegen output.","solutions":["Clean the __generated__ output and compiler caches, then rerun the compiler","Verify the operation doesn't use directives/flags that disable typegen generation","Isolate the named operation and file a Relay compiler bug with a minimal repro"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if (artifact.typegen == null) {\n  throw new Error(`Operation ${artifact.normalization?.name ?? 'MISSING_ENTRY'} lacks a typegen AST`);\n}","typeGuard":"fn has_typegen(a: &ArtifactContent) -> bool { a.typegen.is_some() }","tryCatchPattern":"try {\n  renderArtifact(group);\n} catch (panic) {\n  if (/Expected to have a typegen operation/.test(String(panic))) {\n    cleanAndRecompile();\n  } else throw panic;\n}","preventionTips":["Clear generated output and caches before retrying","Check for transforms/config that suppress typegen output","File upstream bugs with the named operation and minimal repro"],"tags":["compiler","rust","panic","codegen","typegen"],"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"}