{"record":{"id":"8d10f14057cf98fc","repo":"facebook/relay","slug":"expected-a-scalar-field","errorCode":null,"errorMessage":"Expected a scalar field.","messagePattern":"Expected a scalar field\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler/crates/relay-codegen/src/build_ast.rs","lineNumber":2399,"sourceCode":"                        // This means we have to handle two cases:\n                        // - The inline fragment only contains a TypeDiscriminator with the same\n                        //   abstractKey: replace the Fragment w the Discriminator\n                        // - The inline fragment contains other selections: return all the selections\n                        //   minus any Discriminators w the same key\n                        let has_type_discriminator = inline_frag\n                            .selections\n                            .iter()\n                            .any(is_type_discriminator_selection);\n\n                        if has_type_discriminator {\n                            if inline_frag.selections.len() == 1 {\n                                return self.build_type_discriminator(\n                                    if let Selection::ScalarField(field) =\n                                        &inline_frag.selections[0]\n                                    {\n                                        field\n                                    } else {\n                                        panic!(\"Expected a scalar field.\")\n                                    },\n                                );\n                            } else {\n                                let selections = self.build_selections(\n                                    context,\n                                    inline_frag.selections.iter().filter(|selection| {\n                                        !is_type_discriminator_selection(selection)\n                                    }),\n                                );\n                                return Primitive::Key(self.object(object! {\n                                    kind: Primitive::String(CODEGEN_CONSTANTS.inline_fragment),\n                                    selections: selections,\n                                    type_: Primitive::String(\n                                            self.schema.get_type_name(type_condition),\n                                        ),\n                                    abstract_key: Primitive::String(\n                                            generate_abstract_type_refinement_key(\n                                                self.schema,","sourceCodeStart":2381,"sourceCodeEnd":2417,"githubUrl":"https://github.com/facebook/relay/blob/668b1b85e06261aa3b58dabfc51f8b5524a70955/compiler/crates/relay-codegen/src/build_ast.rs#L2381-L2417","documentation":"When a type-discriminating inline fragment (e.g. from @match or a `typename` discriminator pattern) is processed, the compiler expects its single selection to be a scalar field that serves as the type discriminator. If the first selection is not a scalar field, it panics because no scalar field exists to build the discriminator from.","triggerScenarios":"Compiling an inline fragment whose selections[0] is not a ScalarField — e.g. a linked field, fragment spread, or another inline fragment — in a context where Relay builds a type discriminator (typename-based branching).","commonSituations":"Hand-written or transformed documents where @match/module fragments have multiple or non-scalar first selections; custom transforms reordering selections; editing generated code so the discriminator field is no longer first.","solutions":["Ensure the discriminating inline fragment's first (and ideally only) selection is a scalar field such as `__typename` or the resolver payload field.","Remove extra selections from the discriminator fragment or move them into a sibling fragment.","Disable/review custom transforms that reorder or inject selections before build_ast.","Regenerate the document instead of hand-editing compiled/output IR."],"exampleFix":"// before\n... on Note { createdAt viewer { name } }\n\n// after\n... on Note { note } // note is the scalar resolver payload field, first selection","handlingStrategy":"validation","validationCode":"function validateDiscriminatorFragment(inlineFrag) {\n  const first = inlineFrag.selections?.[0];\n  if (!first || first.kind !== 'Field' || first.selections) {\n    throw new Error('Type discriminator inline fragment must start with a scalar field');\n  }\n}","typeGuard":"function startsWithScalarField(inlineFrag) {\n  const first = inlineFrag?.selections?.[0];\n  return first != null && first.kind === 'Field' &&\n    (!first.selectionSet && !first.selections);\n}","tryCatchPattern":"try {\n  compile();\n} catch (e) {\n  if (String(e).includes('Expected a scalar field')) {\n    console.error('Discriminator inline fragment must have a scalar field as its first selection.');\n  } else throw e;\n}","preventionTips":["Put the scalar payload/__typename field first in discriminator fragments","Avoid hand-editing transformed IR","Review custom transforms that reorder selections","Keep @match/@module fragments to a single scalar selection"],"tags":["relay-compiler","graphql","type-discriminator","panic"],"backgroundTag":"invalid-inline-fragment-structure","analyzedSha":"668b1b85e06261aa3b58dabfc51f8b5524a70955","analyzedAt":"2026-09-02T19:57:20.783Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}