hasura/graphql-engine · error · Error
fragment cycle detected through: {0:?}
Error message
fragment cycle detected through: {0:?} What it means
Query validation error: fragment spreads form a cycle (fragment A spreads B which spreads A, directly or transitively). The cycle path is reported as a list of fragment names. Note: an adjacent unused-fragment error exists in the same enum but is not yet thrown.
Source
Thrown at v3/crates/graphql/lang-graphql/src/validation/error.rs:9
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(View on GitHub (pinned to 724551b9ae)
Solutions
- Inspect the reported cycle path and break it by removing one spread
- Extract the shared fields into a third fragment both include instead of referencing each other
- Add a fragment-dependency check/lint in CI for generated documents
Example fix
# before
fragment A on User { name ...B }
fragment B on User { email ...A }
# after
fragment A on User { name ...Shared }
fragment B on User { email ...Shared }
fragment Shared on User { id } Defensive patterns
Strategy: validation
Validate before calling
fn has_fragment_cycle(spreads: &HashMap<Name, Vec<Name>>) -> Option<Vec<Name>> {
// DFS from each fragment; return path when a node repeats
...
} Try / catch
Run the crate's validation pass on the document before execution and handle Error::CycleDetected(path) by reporting the fragment chain to the client/tooling.
Prevention
- Lint fragment dependencies for cycles in CI
- Keep shared fields in leaf fragments that spread nothing
When it happens
Trigger: Running document validation on an executable document whose fragment definitions reference each other, e.g. fragment A on T { ...B } fragment B on T { ...A }.
Common situations: Refactoring fragments that end up referencing each other, codegen or tooling that assembles fragments automatically and creates mutual inclusion, large query documents where the cycle spans many fragments.
Related errors
- validation failed: {0}
- Unexpected value: expecting {expected_kind:}, but found: {fo
- '{name:}' is not a valid GraphQL name.
- '{alias:} is not a valid alias
- {value} is not a valid limit value
AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28).
Data as JSON: /api/errors/582f21061784476c.
Report an issue: GitHub.