{"record":{"id":"b9792bb33a8db661","repo":"hasura/graphql-engine","slug":"cannot-add-mutation-root-field-0-as-it-already-i","errorCode":null,"errorMessage":"Cannot add mutation root field {0} as it already in use","messagePattern":"Cannot add mutation root field (.+?) as it already in use","errorType":"validation","errorClass":"DuplicateRootFieldError","httpStatus":null,"severity":"error","filePath":"v3/crates/metadata-resolve/src/helpers/types.rs","lineNumber":38,"sourceCode":"pub struct NdcColumnForComparison {\n    pub column: DataConnectorColumnName,\n    pub equal_operator: DataConnectorOperatorName,\n}\n\n/// Track the root fields of the GraphQL schema while resolving the metadata.\n/// This is used to ensure that the schema has unique root fields for Query, Mutation and Subscription.\n// NOTE: The `ast::Name` is cheap to clone, so storing them directly without references\npub struct TrackGraphQLRootFields {\n    pub query: BTreeSet<ast::Name>,\n    pub mutation: BTreeSet<ast::Name>,\n    pub subscription: BTreeSet<ast::Name>,\n}\n\n#[derive(Debug, thiserror::Error)]\npub enum DuplicateRootFieldError {\n    #[error(\"Cannot add query root field {0} as it already in use\")]\n    Query(ast::Name),\n    #[error(\"Cannot add mutation root field {0} as it already in use\")]\n    Mutation(ast::Name),\n    #[error(\"Cannot add subscription root field {0} as it already in use\")]\n    Subscription(ast::Name),\n}\n\nimpl TrackGraphQLRootFields {\n    pub fn new() -> Self {\n        Self {\n            query: BTreeSet::new(),\n            mutation: BTreeSet::new(),\n            subscription: BTreeSet::new(),\n        }\n    }\n    pub fn track_query_root_field(\n        &mut self,\n        name: &ast::Name,\n    ) -> Result<(), DuplicateRootFieldError> {\n        if !self.query.insert(name.clone()) {","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/hasura/graphql-engine/blob/724551b9ae87845594ef0408cff0e50eb6c90dc5/v3/crates/metadata-resolve/src/helpers/types.rs#L20-L56","documentation":"DuplicateRootFieldError::Mutation: the same situation as the Query variant but for the Mutation root type — two metadata entries attempt to register a GraphQL mutation root field with an identical name.","triggerScenarios":"Registering two mutations (commands) with the same GraphQL name on the Mutation root, e.g. two create_/update_ commands both named insert_user in different modules.","commonSituations":"Copy-pasted command definitions, multiple data connectors each defining a mutation with the same name, refactors that moved a command without renaming it.","solutions":["Rename one mutation's GraphQL field name to be unique","Remove the stale duplicate command from metadata","Namespace mutation names per connector/domain (e.g. orders_insert vs users_insert)"],"exampleFix":"# before\n- kind: Command\n  name: insert_user\n  # in two different modules\n\n# after\n- kind: Command\n  name: insert_user_v2   # unique name in the second module","handlingStrategy":"validation","validationCode":"if !mutation_fields.insert(name.clone()) {\n    return Err(format!(\"duplicate mutation root field: {name}\"));\n}","typeGuard":null,"tryCatchPattern":"match err {\n    DuplicateRootFieldError::Mutation(name) => eprintln!(\"two mutations expose '{name}'; rename one\"),\n    _ => {}\n}","preventionTips":["Prefix mutations with entity + verb (user_insert, user_update)","Namespace per connector when combining multiple data sources","Check for clones after copy-pasting command metadata"],"tags":["graphql","metadata","naming","duplicate","mutation"],"backgroundTag":"duplicate-graphql-field","analyzedSha":"724551b9ae87845594ef0408cff0e50eb6c90dc5","analyzedAt":"2026-08-28T07:32:55.105Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}