hasura/graphql-engine · error · Error
Duplicate alternative mode identifier: '{0}'
Error message
Duplicate alternative mode identifier: '{0}' What it means
Hard error from auth config generation: two entries in the auth config declared the same identifier for an alternative auth mode, but identifiers must be unique so the engine can unambiguously select a mode.
Source
Thrown at v3/crates/auth/hasura-authn/src/lib.rs:293
impl Warning {
pub fn should_be_an_error(&self, flags: &open_dds::flags::OpenDdFlags) -> bool {
match self {
Warning::InvalidHeaderName(_) | Warning::InvalidHeaderValue(_, _) => {
flags.contains(open_dds::flags::Flag::DisallowInvalidHeadersInAuthConfig)
}
_ => false,
}
}
}
#[derive(Debug, thiserror::Error, PartialEq)]
pub enum Error {
#[error("Invalid URL for auth webhook: {0}")]
InvalidAuthWebhookUrl(String),
#[error("{0}")]
AuthConfigWarningsAsErrors(SeparatedBy<Warning>),
#[error("Duplicate alternative mode identifier: '{0}'")]
DuplicateAlternativeModeIdentifier(String),
}
// A small utility type which exists for the sole purpose of displaying a vector with a certain
// separator.
#[derive(Debug, PartialEq)]
pub struct SeparatedBy<T> {
pub lines_of: Vec<T>,
pub separator: String,
}
impl<T: Display> Display for SeparatedBy<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for (index, elem) in self.lines_of.iter().enumerate() {
elem.fmt(f)?;
if index < self.lines_of.len() - 1 {
self.separator.fmt(f)?;
}View on GitHub (pinned to 724551b9ae)
Solutions
- Find the duplicated identifier in the alternative modes list and rename one entry to a unique value
- Grep the auth config for the identifier shown in the message to locate both occurrences
- Add a CI lint/duplication check over mode identifiers before merging config changes
Example fix
// before
modes:
- id: "admin"
...
- id: "admin"
...
// after
modes:
- id: "admin"
...
- id: "admin-backup"
... Defensive patterns
Strategy: validation
Validate before calling
use std::collections::HashSet;
let mut ids = HashSet::new();
for mode in &auth_config.modes {
if !ids.insert(mode.identifier.clone()) {
return Err(format!("duplicate alternative mode identifier: {}", mode.identifier));
}
} Type guard
fn modeIdsUnique(modes: &[Mode]) -> bool {
let mut s = std::collections::HashSet::new();
modes.iter().all(|m| s.insert(m.identifier.clone()))
} Prevention
- Namespace mode identifiers per team (e.g. teamA-admin)
- Run a duplicate-identifier lint on auth configs in CI
- Rename rather than copy-paste mode blocks
When it happens
Trigger: The `modes`/alternative modes list of the auth config contains two entries whose mode identifier strings are equal (case-sensitive comparison of the configured identifiers).
Common situations: Copy-pasting an auth mode block and forgetting to rename its identifier, or merging auth configs from multiple teams that both defined a mode like "admin".
Related errors
- Tried to combine a predicate with a literal in argument pres
- Header '{0}', used in the auth config, is not a valid header
- Header value '{0}' is not a valid header value for header '{
- Invalid URL for auth webhook: {0}
- {0}
AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28).
Data as JSON: /api/errors/332b40cf9e177007.
Report an issue: GitHub.