hasura/graphql-engine · error · Error
fragment not defined in the document: {0}
Error message
fragment not defined in the document: {0} What it means
Thrown when a query document spreads a named fragment (e.g. `...MyFragment`) that is not defined anywhere in the same executable document. The validator looks up fragment definitions when collecting fields (validation/collect.rs collect_fields_internal) and in check_fragment_cycles (validation.rs:127); a missing definition yields UnknownFragment carrying the fragment name. GraphQL requires every fragment spread to resolve within the same document.
Source
Thrown at v3/crates/graphql/lang-graphql/src/validation/error.rs:14
use thiserror::Error;
use crate::ast::{common as ast, spanning};
pub type Result<T> = core::result::Result<T, Error>;
#[derive(Error, Debug, Clone)]
pub enum Error {
#[error("fragment cycle detected through: {0:?}")]
CycleDetected(Vec<ast::Name>),
// TODO, this error isn't thrown yet
#[error("unused fragment: {0}")]
FragmentNotUsed(ast::Name),
#[error("fragment not defined in the document: {0}")]
UnknownFragment(ast::Name),
#[error("{} is defined on a non-composite type: {type_name}", match fragment_name { None => "inline fragment".to_owned(), Some(fragment_name) => format!("fragment {fragment_name}")})]
FragmentOnNonCompositeType {
fragment_name: Option<ast::Name>,
type_name: ast::TypeName,
},
#[error("fragment of type {fragment_type} cannot be spread on type {selection_type}")]
FragmentCannotBeSpread {
selection_type: ast::TypeName,
fragment_type: ast::TypeName,
},
// TODO, this error isn't thrown yet
#[error(
"a selection set is specified on field '{field_name}' of non-composite type: {type_name}"
)]
SelectionOnNonCompositeType {
field_name: ast::Name,
type_name: ast::TypeName,View on GitHub (pinned to 724551b9ae)
Solutions
- Ensure every `...Name` spread has a matching `fragment Name on Type { ... }` definition in the same document sent to the server
- Check for typos/case mismatches between the spread name and the fragment definition name
- If building the document programmatically, concatenate all fragment definitions from your query source before calling validation/execution
Example fix
// before
query { user { ...UserFields } }
// after
query { user { ...UserFields } }
fragment UserFields on User { id name } Defensive patterns
Strategy: validation
Validate before calling
let defined: HashSet<&str> = doc.definitions().iter().filter_map(|d| match d { Definition::Fragment(f) => Some(f.name.as_str()), _ => None }).collect();
for spread in collect_spreads(doc) { assert!(defined.contains(spread), "missing fragment {spread}"); } Type guard
fn has_fragment_def(doc: &Document<()>, name: &str) -> bool { doc.definitions().iter().any(|d| matches!(d, Definition::Fragment(f) if f.name.as_str() == name)) } Try / catch
match validator.validate(&schema, &doc) { Err(e @ Error::UnknownFragment(_)) => report_user_error(e), r => r } Prevention
- Always ship fragment definitions in the same document as their spreads
- Use a query builder that tracks fragments automatically
- Add a preflight check that every `...Name` spread has a definition
When it happens
Trigger: Executing a query string that contains `...SomeFragment` without including the corresponding `fragment SomeFragment on X { ... }` definition in the same document; concatenating query strings but dropping the fragment portion; typos in the fragment name after `...`.
Common situations: Client code sends only the query operation while fragment definitions live in a different string/file that was never appended; codegen splits queries and fragments and only the operation is transmitted; refactoring renames a fragment but not all its spreads.
Related errors
- {} is defined on a non-composite type: {type_name}
- validation failed: {0}
- Unexpected value: expecting {expected_kind:}, but found: {fo
- '{name:}' is not a valid GraphQL name.
- '{alias:} is not a valid alias
AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28).
Data as JSON: /api/errors/f8834b5f76718b55.
Report an issue: GitHub.