hasura/graphql-engine · error · DuplicateRootFieldError

Cannot add subscription root field {0} as it already in use

Error message

Cannot add subscription root field {0} as it already in use

What it means

DuplicateRootFieldError::Subscription: two metadata components try to register a GraphQL subscription root field with the same name. Subscription root fields are tracked in their own BTreeSet, so collisions are detected independently of Query and Mutation.

Source

Thrown at v3/crates/metadata-resolve/src/helpers/types.rs:40

    pub equal_operator: DataConnectorOperatorName,
}

/// Track the root fields of the GraphQL schema while resolving the metadata.
/// This is used to ensure that the schema has unique root fields for Query, Mutation and Subscription.
// NOTE: The `ast::Name` is cheap to clone, so storing them directly without references
pub struct TrackGraphQLRootFields {
    pub query: BTreeSet<ast::Name>,
    pub mutation: BTreeSet<ast::Name>,
    pub subscription: BTreeSet<ast::Name>,
}

#[derive(Debug, thiserror::Error)]
pub enum DuplicateRootFieldError {
    #[error("Cannot add query root field {0} as it already in use")]
    Query(ast::Name),
    #[error("Cannot add mutation root field {0} as it already in use")]
    Mutation(ast::Name),
    #[error("Cannot add subscription root field {0} as it already in use")]
    Subscription(ast::Name),
}

impl TrackGraphQLRootFields {
    pub fn new() -> Self {
        Self {
            query: BTreeSet::new(),
            mutation: BTreeSet::new(),
            subscription: BTreeSet::new(),
        }
    }
    pub fn track_query_root_field(
        &mut self,
        name: &ast::Name,
    ) -> Result<(), DuplicateRootFieldError> {
        if !self.query.insert(name.clone()) {
            return Err(DuplicateRootFieldError::Query(name.clone()));
        }

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Rename one of the colliding subscription root fields
  2. Disable the subscription on one of the models/commands if redundant
  3. Remove duplicated metadata entries

Example fix

# before
Model A: subscription field "events"
Model B: subscription field "events"

# after
Model B: subscription field "order_events"
Defensive patterns

Strategy: validation

Validate before calling

if !subscription_fields.insert(name.clone()) {
    return Err(format!("duplicate subscription root field: {name}"));
}

Try / catch

match err {
    DuplicateRootFieldError::Subscription(name) => eprintln!("two subscriptions expose '{name}'; rename or disable one"),
    _ => {}
}

Prevention

When it happens

Trigger: Defining two subscription-producing metadata objects (e.g. two models with subscriptions enabled, or commands exposed via subscription) whose GraphQL root field names are identical.

Common situations: Enabling subscriptions on multiple models that resolve to the same field name, duplicated subscription metadata across environments.

Related errors


AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28). Data as JSON: /api/errors/0cca254c121771d2. Report an issue: GitHub.