{"record":{"id":"e7e140b059c58313","repo":"facebook/relay","slug":"expected-parent-type","errorCode":null,"errorMessage":"Expected parent type","messagePattern":"Expected parent type","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler/crates/relay-transforms/src/relay_resolvers.rs","lineNumber":209,"sourceCode":"    pub resolver_type: ResolverSchemaGenType,\n    pub return_fragment: Option<WithLocation<FragmentDefinitionName>>,\n}\nassociated_data_impl!(RelayResolverMetadata);\n\nimpl RelayResolverMetadata {\n    pub fn field<'schema>(&self, schema: &'schema SDLSchema) -> &'schema Field {\n        schema.field(self.field_id)\n    }\n\n    pub fn field_name(&self, schema: &SDLSchema) -> StringKey {\n        self.field(schema).name.item\n    }\n\n    pub fn field_parent_type_name(&self, schema: &SDLSchema) -> StringKey {\n        let parent_type = self\n            .field(schema)\n            .parent_type\n            .expect(\"Expected parent type\");\n        match parent_type {\n            Type::Interface(interface_id) => schema.interface(interface_id).name.item.0,\n            Type::Object(object_id) => schema.object(object_id).name.item.0,\n            _ => panic!(\"Unexpected parent type for resolver.\"),\n        }\n    }\n\n    pub fn generate_local_resolver_name(&self, schema: &SDLSchema) -> StringKey {\n        resolver_import_alias(self.field_parent_type_name(schema), self.field_name(schema))\n    }\n    pub fn generate_local_resolver_type_name(&self, schema: &SDLSchema) -> StringKey {\n        resolver_type_import_alias(self.field_parent_type_name(schema), self.field_name(schema))\n    }\n}\n","sourceCodeStart":191,"sourceCodeEnd":224,"githubUrl":"https://github.com/facebook/relay/blob/668b1b85e06261aa3b58dabfc51f8b5524a70955/compiler/crates/relay-transforms/src/relay_resolvers.rs#L191-L224","documentation":"This panic fires in Relay compiler's relay_resolvers transform when a field's parent type is missing from the schema while generating a local @relay_resolver name/type. The schema invariant that every field has a parent type was violated, so the transform cannot derive the resolver's parent type name and aborts. It guards a Rust Option returned by schema lookups, meaning the schema was built incompletely or the transform ran on a field not attached to a type.","triggerScenarios":"Calling generate_local_resolver_name or generate_local_resolver_type_name on a field whose parent_type is None — e.g. the field was synthesized outside normal schema construction, the AST-to-IR schema build skipped the parent link, or the resolver transform was run on a hand-constructed SDLSchema fragment missing the parent object/interface entry.","commonSituations":"Custom compiler pipelines that build/patch SDLSchema programmatically; schema-generation scripts that insert relay_resolver fields without registering the parent type; mid-upgrade states of the Relay compiler where schema construction changed.","solutions":["Inspect the schema: ensure the field's parent type (object/interface) is registered in SDLSchema before running the relay_resolvers transform.","Rebuild the schema through the normal CompilerState/parse pipeline instead of manual construction so parent_type is always populated.","Check whether a custom transform earlier in the pipeline detached or replaced the field; run transforms in the documented order.","If constructing schemas in tests, use the test schema helpers rather than hand-rolled schema structs."],"exampleFix":"// before\nlet field = /* manually built field with parent_type: None */;\nlet name = field.parent_type_name(&schema); // panics\n// after\nlet field = schema.field(parent_object_id, field_name); // schema-resolved, parent_type always set\nlet name = field.parent_type_name(&schema);","handlingStrategy":"validation","validationCode":"// Before invoking resolver name generation, assert the parent exists:\nif field.parent_type.is_none() {\n    panic!(\"field {} has no parent type; schema is incomplete\", field.name.item.0);\n}\n// or resolve via the schema instead:\nlet parent = field.parent_type.unwrap_or_else(|| Type::Object(schema.objects_len() - 1));","typeGuard":"fn has_parent_type(field: &Field) -> bool {\n    field.parent_type.is_some()\n}","tryCatchPattern":"// Rust panics are not catchable by Result; gate the call:\nif has_parent_type(&field) {\n    let name = field.parent_type_name(&schema);\n} else {\n    return Err(anyhow!(\"resolver field missing parent type\"));\n}","preventionTips":["Build schemas only through the standard parse/build pipeline, never by manual struct construction","Add an assertion test that every field in your test schema has a parent_type","Run the full compiler (not just one transform) so invariants are established","Keep transform order matching Relay's documented pipeline"],"tags":["relay","graphql","compiler-transform","panic","schema"],"backgroundTag":"missing-schema-parent-type","analyzedSha":"668b1b85e06261aa3b58dabfc51f8b5524a70955","analyzedAt":"2026-09-02T19:57:20.783Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}