hasura/graphql-engine · error · RelayError
Found multiple models {model_1:}, {model_2:} that implement
Error message
Found multiple models {model_1:}, {model_2:} that implement the same object type {object_type:} to be global ID sources. What it means
Relay stage error: two different models (both named in the message) that implement the same object type are marked globalIdSource: true. Relay requires a unique global ID source per object type; the resolver cannot pick between them and aborts. Note the doubled space in the message is cosmetic.
Source
Thrown at v3/crates/metadata-resolve/src/stages/relay/mod.rs:39
Ok(())
}
#[derive(Debug, thiserror::Error)]
pub enum RelayError {
#[error(
"'globalIdFields' for type {object_type:} found, but no model found with 'globalIdSource: true' for type {object_type:}"
)]
GlobalIdSourceNotDefined {
object_type: Qualified<CustomTypeName>,
},
#[error(
"Model {model_name:} is marked as a global ID source but there are no global id fields present in the related object type {type_name:}"
)]
NoGlobalFieldsPresentInGlobalIdSource {
type_name: Qualified<CustomTypeName>,
model_name: ModelName,
},
#[error(
"Found multiple models {model_1:}, {model_2:} that implement the same object type {object_type:} to be global ID sources."
)]
DuplicateModelGlobalIdSource {
model_1: Qualified<ModelName>,
model_2: Qualified<ModelName>,
object_type: Qualified<CustomTypeName>,
},
#[error("model {model_name:} with arguments is unsupported as a global ID source")]
ModelWithArgumentsAsGlobalIdSource { model_name: Qualified<ModelName> },
}
View on GitHub (pinned to 724551b9ae)
Solutions
- Pick one model to be the global ID source and remove globalIdSource: true from the other
- If both models are accidental duplicates, delete one entirely
- If types are meant to be distinct, fix the objectType mapping so they no longer collide
Example fix
# before
models:
- name: Users
objectType: User
globalIdSource: true
- name: UsersV2
objectType: User
globalIdSource: true
# after
models:
- name: Users
objectType: User
globalIdSource: true
- name: UsersV2
objectType: User Defensive patterns
Strategy: validation
Validate before calling
fn check_single_global_id_source(models: &[Model]) -> Result<(), String> {
let mut seen: HashMap<_, Vec<_>> = HashMap::new();
for m in models {
if m.global_id_source { seen.entry(m.object_type.clone()).or_default().push(m.name.clone()); }
}
for (ty, names) in seen {
if names.len() > 1 { return Err(format!("multiple globalIdSource models for {ty}: {names:?}")); }
}
Ok(())
} Try / catch
catch DuplicateModelGlobalIdSource and print both model qualified names plus the shared object type
Prevention
- One globalIdSource per object type across all namespaces
- When duplicating models across subgraphs, clear globalIdSource on copies
When it happens
Trigger: Two models with globalIdSource: true whose objectType mappings resolve to the same Qualified<CustomTypeName> — often the same model defined in two subgraphs/namespaces, or a duplicated model config.
Common situations: Copying a Relay-enabled model into another namespace without clearing the flag; consolidating models onto one type while both keep globalIdSource; federation-style setups where the same type is implemented per-subgraph.
Related errors
- 'globalIdFields' for type {object_type:} found, but no model
- Model {model_name:} is marked as a global ID source but ther
- model {model_name:} with arguments is unsupported as a globa
- Multiple relationships named {relationship_name} defined for
- error in getting server feature flags %w
AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28).
Data as JSON: /api/errors/91af4b8a04294a4d.
Report an issue: GitHub.