{"record":{"id":"601595a04e3e294e","repo":"hasura/graphql-engine","slug":"graphql-configuration-should-be-defined-only-once","errorCode":null,"errorMessage":"graphql configuration should be defined only once in supergraph","messagePattern":"graphql configuration should be defined only once in supergraph","errorType":"validation","errorClass":"GraphqlConfigError","httpStatus":null,"severity":"error","filePath":"v3/crates/metadata-resolve/src/stages/graphql_config/error.rs","lineNumber":9,"sourceCode":"use graphql_types as ast;\n\nuse crate::types::error::ContextualError;\n\n#[derive(Debug, thiserror::Error)]\npub enum GraphqlConfigError {\n    #[error(\"graphql configuration is not defined in supergraph\")]\n    MissingGraphqlConfig,\n    #[error(\"graphql configuration should be defined only once in supergraph\")]\n    MultipleGraphqlConfigDefinition,\n    #[error(\n        \"the fieldName for limitInput needs to be defined in GraphqlConfig, when models have a selectMany graphql API\"\n    )]\n    MissingLimitFieldInGraphqlConfig,\n    #[error(\n        \"the fieldName for offsetInput needs to be defined in GraphqlConfig, when models have a selectMany graphql API\"\n    )]\n    MissingOffsetFieldInGraphqlConfig,\n    #[error(\n        \"the filterInput needs to be defined in GraphqlConfig, when models have filterExpressionType\"\n    )]\n    MissingFilterInputFieldInGraphqlConfig,\n    #[error(\n        \"the orderByInput needs to be defined in GraphqlConfig, when models have orderByExpressionType\"\n    )]\n    MissingOrderByInputFieldInGraphqlConfig,\n    #[error(","sourceCodeStart":1,"sourceCodeEnd":27,"githubUrl":"https://github.com/hasura/graphql-engine/blob/724551b9ae87845594ef0408cff0e50eb6c90dc5/v3/crates/metadata-resolve/src/stages/graphql_config/error.rs#L1-L27","documentation":"Thrown by the graphql_config resolution stage when the supergraph contains more than one GraphqlConfig definition. The supergraph must have exactly one `graphql` configuration block; duplicates create ambiguity about which limit/offset/filter/orderBy field names apply. Raised during metadata resolution.","triggerScenarios":"Resolving supergraph metadata that contains two or more objects of the GraphqlConfig type (e.g. two subgraphs each contributing their own `graphql` config, or a copy-paste duplication in a hand-written metadata file).","commonSituations":"Federating/merging multiple subgraph metadata files that each already had a graphql config; copy-pasting a config block while editing metadata; tooling that injects a default graphql config into a document that already declares one.","solutions":["Locate all GraphqlConfig objects in the supergraph and delete all but one","If merging subgraphs, designate one source of truth for the graphql config and strip it from the others before merging","If tooling auto-injects a default config, disable the injection when the document already declares one"],"exampleFix":"// before\n{\"graphql\": {\"limitInput\": {\"fieldName\": \"limit\"}}, \"subgraphs\": [{\"graphql\": {\"limitInput\": {\"fieldName\": \"l\"}}}]}\n// after\n{\"graphql\": {\"limitInput\": {\"fieldName\": \"limit\"}}, \"subgraphs\": [{}]}","handlingStrategy":"validation","validationCode":"let count = metadata.objects.iter().filter(|o| o.type_ == \"GraphqlConfig\").count();\nassert_eq!(count, 1, \"expected exactly one GraphqlConfig, found {}\", count);","typeGuard":"fn has_single_graphql_config(md: &Metadata) -> bool {\n    md.objects.iter().filter(|o| o.type_ == \"GraphqlConfig\").count() == 1\n}","tryCatchPattern":"match resolve_metadata(supergraph) {\n    Err(ContextualError::GraphqlConfig(GraphqlConfigError::MultipleGraphqlConfigDefinition)) => /* dedupe configs and retry */,\n    other => other,\n}","preventionTips":["Deduplicate graphql config during subgraph merges","Make exactly one subgraph own the graphql config","Add a merge lint step that rejects duplicate GraphqlConfig objects"],"tags":["graphql","metadata","supergraph","duplicate-config"],"backgroundTag":"duplicate-config-definition","analyzedSha":"724551b9ae87845594ef0408cff0e50eb6c90dc5","analyzedAt":"2026-08-28T07:32:55.105Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}