{"record":{"id":"31544c100e5fb64c","repo":"facebook/relay","slug":"unexpected-parent-type-for-resolver","errorCode":null,"errorMessage":"Unexpected parent type for resolver.","messagePattern":"Unexpected parent type for resolver\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler/crates/relay-codegen/src/build_ast.rs","lineNumber":1163,"sourceCode":"    ) -> Primitive {\n        let field_name = resolver_metadata.field_name(self.schema);\n        // Include both field_arguments and fragment_arguments (see comment\n        // in build_normalization_relay_resolver_exec_and_read_time).\n        let all_arguments: Vec<_> = resolver_metadata\n            .field_arguments\n            .iter()\n            .chain(resolver_metadata.fragment_arguments.iter())\n            .cloned()\n            .collect();\n        let args = self.build_arguments(&all_arguments);\n        let is_output_type = resolver_metadata\n            .output_type_info\n            .normalization_ast_should_have_is_output_type_true();\n\n        let field_type = match resolver_metadata.field(self.schema).parent_type.unwrap() {\n            Type::Interface(interface_id) => self.schema.interface(interface_id).name.item.0,\n            Type::Object(object_id) => self.schema.object(object_id).name.item.0,\n            _ => panic!(\"Unexpected parent type for resolver.\"),\n        };\n\n        let variable_name = resolver_metadata.generate_local_resolver_name(self.schema);\n        let kind = if resolver_metadata.live {\n            CODEGEN_CONSTANTS.relay_live_resolver\n        } else {\n            CODEGEN_CONSTANTS.relay_resolver\n        };\n        Primitive::Key(self.object(object! {\n            name: Primitive::String(field_name),\n            args: match args {\n                None => Primitive::SkippableNull,\n                Some(key) => Primitive::Key(key),\n            },\n            kind: Primitive::String(kind),\n            storage_key: match args {\n                None => Primitive::SkippableNull,\n                Some(key) => {","sourceCodeStart":1145,"sourceCodeEnd":1181,"githubUrl":"https://github.com/facebook/relay/blob/668b1b85e06261aa3b58dabfc51f8b5524a70955/compiler/crates/relay-codegen/src/build_ast.rs#L1145-L1181","documentation":"When generating the normalization AST for a worker-style relay resolver, the resolver's parent type must be an object or interface. The code unwraps resolver_metadata parent_type with .unwrap() and matches only Interface/Object variants; any other type (scalar, union, enum) hits the panic.","triggerScenarios":"build_normalization_relay_resolver_execution_time_for_worker encounters a resolver whose declared parent type is not an object or interface — e.g. a resolver attached to a union, scalar, or with a missing/incorrect parent_type in its metadata.","commonSituations":"Defining a resolver on a union type where the codegen only supports object/interface parents; stale resolver metadata after refactoring a type from interface to union; misconfigured @relay_resolver parentType value.","solutions":["Move the resolver so its parent type is an object or interface type.","Fix the resolver metadata/parentType declaration so it points at the correct object/interface.","If the parent is legitimately a union, restructure the resolver per fragment or update the compiler to support unions on that path.","Regenerate metadata after schema refactors so parent_type reflects the current schema."],"exampleFix":"// before\nunion SearchResult = User | Story\nextend type SearchResult @relay_resolver(...)\n// after: attach resolver to a concrete parent\nextend type Query @relay_resolver(name: \"searchResolver\")\n","handlingStrategy":"validation","validationCode":"fn resolver_parent_type_ok(schema: &Schema, meta: &ResolverMetadata) -> bool {\n    matches!(meta.parent_type, Some(Type::Object(_)) | Some(Type::Interface(_)))\n}\n","typeGuard":"fn is_object_or_interface(t: &Type) -> bool {\n    matches!(t, Type::Object(_) | Type::Interface(_))\n}\n","tryCatchPattern":"let result = std::panic::catch_unwind(|| build_normalization_relay_resolver(...));\nif result.is_err() { report(\"resolver parent type must be object or interface\"); }\n","preventionTips":["Only define relay resolvers on object or interface parents.","Re-generate resolver metadata after schema refactors (e.g. type -> union changes).","Lint @relay_resolver usages for unsupported parent types before compiling."],"tags":["graphql","resolver","codegen","parent-type"],"backgroundTag":"unexpected-resolver-metadata","analyzedSha":"668b1b85e06261aa3b58dabfc51f8b5524a70955","analyzedAt":"2026-09-02T19:57:20.783Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}