facebook/relay · error
Expect fragment to exist.
Error message
Expect fragment to exist.
What it means
The root_variables transform resolves each fragment spread by looking the fragment definition up in the program and expects it to exist ("Expect fragment to exist."). It needs the definition to read @arguments variable definitions and type-check root variables passed to the spread. A missing definition means the spread references a fragment that was never added to the compiled program.
Source
Thrown at compiler/crates/relay-transforms/src/root_variables.rs:268
&& let Some(relay_resolver_metadata) = RelayResolverMetadata::from(directive)
{
for arg in relay_resolver_metadata.field_arguments.iter() {
if let Value::Variable(var) = &arg.value.item
&& self.is_root_variable(var.name.item)
{
self.record_root_variable_usage(&var.name, &var.type_);
}
}
}
self.default_visit_directive(directive);
}
fn visit_fragment_spread(&mut self, spread: &FragmentSpread) {
self.visit_directives(&spread.directives);
let fragment = self
.program
.fragment(spread.fragment.item)
.expect("Expect fragment to exist.");
// Detect root variables being passed as the value of @arguments;
// recover the expected type from the corresponding argument definitions.
if !fragment.variable_definitions.is_empty() {
for arg in spread.arguments.iter() {
if let Value::Variable(var) = &arg.value.item
&& let Some(def) = fragment
.variable_definitions
.named(VariableName(arg.name.item.0))
&& self.is_root_variable(var.name.item)
{
self.record_root_variable_usage(&var.name, &def.type_);
}
}
}
// Merge any root variables referenced by the spread fragment
// into this (parent) fragment's arguments.View on GitHub (pinned to 668b1b85e0)
Solutions
- Compile the entire program (all documents) together so every spread's fragment is present.
- Check your relay compiler config (include/exclude globs, docs/extension) so the fragment's file is picked up.
- Verify earlier validation passes (undefined fragment detection) run before root_variables.
- If the fragment was intentionally removed, remove the stale spread from the operation.
Example fix
// relay.config.js — before include: ['src/queries/**'], // after include: ['src/**'], // ensure fragments referenced by queries are compiled
Defensive patterns
Strategy: validation
Validate before calling
if program.fragment(spread.fragment.item).is_none() {
return Err(vec![Diagnostic::error(format!("Undefined fragment '{}'", spread.fragment.item))]));
} Type guard
fn spread_resolvable(program: &Program, spread: &FragmentSpread) -> bool { program.fragment(spread.fragment.item).is_some() } Try / catch
let Some(fragment) = program.fragment(spread.fragment.item) else { continue; }; Prevention
- Include all fragment-defining files in the compiler's document set.
- Run undefined-fragment validation before root_variables.
- Avoid per-file compilation for programs with cross-file spreads.
When it happens
Trigger: A fragment spread whose target fragment is absent from the program — compiling per-file so the spread's fragment lives in an uncompiled module, a typo'd fragment name that skipped earlier validation, or a transform order where fragments were pruned before root_variables runs.
Common situations: Per-document compilation instead of whole-program compilation; fragments declared in files excluded from the compiler's document list; monorepo setups where the include globs miss the fragment's module.
Related errors
- Expect to have a fragment node.
- commitMutation: Expected mutation operation
- commitMutation: Expected mutation operation
- commitMutation: Expected mutation to be of type request
- Unexpected RelayResolverMetadata on fragment spread while ge
AI-assisted analysis of facebook/relay@668b1b85e0 (2026-09-02).
Data as JSON: /api/errors/dfa213d4be01b3f7.
Report an issue: GitHub.