facebook/relay · error

Unexpected RelayResolverMetadata on fragment spread while ge

Error message

Unexpected RelayResolverMetadata on fragment spread while generating normalization AST.

What it means

RelayResolver metadata on a plain fragment spread is only supported when generating Reader ASTs. When generating Normalization ASTs, the compiler expects all resolver fragment spreads to have been inlined into inline fragments, so encountering one panics.

Source

Thrown at compiler/crates/relay-codegen/src/build_ast.rs:1536

                            definition: WithLocation::generated(resolver_metadata.field_id),
                            arguments: resolver_metadata.field_arguments.clone(),
                            directives: frag_spread
                                .directives
                                .iter()
                                .filter(|directive| {
                                    directive.name.item
                                        != RequiredMetadataDirective::directive_name()
                                })
                                .cloned()
                                .collect(),
                        };
                        self.build_scalar_field(&scalar_field)
                    } else {
                        self.build_reader_relay_resolver(resolver_metadata, Some(primitive))
                    }
                }
                // We expect all RelayResolver fragment spreads to be inlined into inline fragment spreads when generating Normalization ASTs.
                CodegenVariant::Normalization => panic!(
                    "Unexpected RelayResolverMetadata on fragment spread while generating normalization AST."
                ),
            };

            if let Some(required_metadata) =
                RequiredMetadataDirective::find(&frag_spread.directives)
            {
                self.build_required_field(required_metadata, resolver_primitive)
            } else if let Some(catch_metadata) =
                CatchMetadataDirective::find(&frag_spread.directives)
            {
                self.build_catch_node(catch_metadata, resolver_primitive)
            } else {
                resolver_primitive
            }
        } else {
            primitive
        }

View on GitHub (pinned to 668b1b85e0)

Solutions

  1. Let the relay compiler pipeline generate the resolver fragment usage (inline fragment form) rather than hand-writing spreads with resolver directives.
  2. Remove resolver metadata directives from the fragment spread if it isn't a resolver, and reference the fragment normally.
  3. Run normalization codegen only on documents that have gone through the client-edge inlining pass; fix custom build scripts to include that pass.
  4. Align relay compiler versions across steps so normalization codegen matches the document format produced upstream.

Example fix

// before
... on Query {
  ...MyResolverFragment @relay_resolver
}
// after: use the compiler-generated inline fragment form
... on Query {
  ... on Query @inline @refetchable(queryName: "MyResolverQuery") { ... }
}
Defensive patterns

Strategy: validation

Validate before calling

fn spread_is_normalization_safe(spread: &FragmentSpread) -> bool {
    RelayResolverMetadata::find(&spread.directives).is_none()
}

Type guard

fn spread_has_resolver_metadata(spread: &FragmentSpread) -> bool {
    RelayResolverMetadata::find(&spread.directives).is_some()
}

Try / catch

let result = std::panic::catch_unwind(|| build_fragment_spread(...));
if result.is_err() { report("resolver fragment spread reached normalization codegen; run inlining pass first"); }

Prevention

When it happens

Trigger: A fragment spread (`...SomeResolverFragment`) whose directives contain RelayResolverMetadata is processed by build_fragment_spread while CodegenVariant::Normalization is active (reached via build_reader_client_edge callers' normalization counterpart).

Common situations: Hand-writing a fragment spread with @relay_resolver-style metadata instead of relying on generated inline fragments; using a custom/partial compile step that skips the inlining pass; feeding documents compiled by a different relay version into normalization codegen.

Related errors


AI-assisted analysis of facebook/relay@668b1b85e0 (2026-09-02). Data as JSON: /api/errors/40c8b43eba74a5b3. Report an issue: GitHub.