hasura/graphql-engine · critical · StartupError
could not read the auth config - {0}
Error message
could not read the auth config - {0} What it means
Variant StartupError::ReadAuth wrapping the underlying anyhow error raised while reading or parsing the auth configuration. It surfaces as 'could not read the auth config - <cause>' during engine startup and is classified as user-visible (ErrorVisibility::User), i.e. it's the operator's responsibility, not an internal bug.
Source
Thrown at v3/crates/engine/src/types.rs:25
use tracing_util::{ErrorVisibility, TraceableError};
#[derive(Clone)] // Cheap to clone as heavy fields are wrapped in `Arc`
pub struct EngineState {
pub expose_internal_errors: ExposeInternalErrors,
pub http_context: HttpContext,
pub graphql_state: Arc<gql::schema::Schema<GDS>>,
pub resolved_metadata: Arc<metadata_resolve::Metadata>,
pub jsonapi_catalog: Arc<jsonapi::Catalog>,
pub auth_config: Arc<ResolvedAuthConfig>,
pub graphql_websocket_server:
Arc<graphql_ws::WebSocketServer<graphql_ws::NoOpWebSocketMetrics>>,
pub auth_mode_header: String,
}
#[derive(thiserror::Error, Debug)]
#[allow(clippy::enum_variant_names)]
pub enum StartupError {
#[error("could not read the auth config - {0}")]
ReadAuth(anyhow::Error),
#[error("failed to build engine state - {0}")]
ReadSchema(anyhow::Error),
}
impl TraceableError for StartupError {
fn visibility(&self) -> tracing_util::ErrorVisibility {
ErrorVisibility::User
}
}
/// The type of request being made to the engine
pub enum RequestType {
Http,
WebSocket,
}
impl RequestType {View on GitHub (pinned to 724551b9ae)
Solutions
- Check the wrapped cause after the dash — it names the exact read/parse failure
- Validate the auth config JSON with jq or a JSON schema before deploying
- Ensure the file path in your server config points to the intended auth config
- After upgrading the engine, re-check the expected auth config format
Example fix
// before
{"authn": {"authentication": {"jwt": {"issuer": ...}}}} // malformed/truncated
// after
# validate first
jq . auth_config.json && engine --authn-config-path ./auth_config.json Defensive patterns
Strategy: validation
Validate before calling
let raw = std::fs::read_to_string(&path).map_err(anyhow::Error::from)?;
serde_json::from_str::<AuthConfig>(&raw)
.map_err(|e| StartupError::ReadAuth(e.into()))?; Type guard
fn is_read_auth(e: &StartupError) -> bool { matches!(e, StartupError::ReadAuth(_)) } Try / catch
Match StartupError::ReadAuth(err) at startup and print err (the wrapped cause) plus the configured path; exit non-zero.
Prevention
- Validate auth config with jq/schema checks in CI
- Template auth configs with a lint step after envsubst
- Pin engine version and re-validate config format on upgrade
When it happens
Trigger: Engine state construction (build engine state) when reading the authn config file fails (missing/unreadable file) or when parsing its contents (e.g. malformed JSON/JWKS structure) produces an error wrapped into this variant.
Common situations: Missing auth config in deployments, malformed JSON after templating/envsubst, wrong file referenced by config, changed auth config schema between engine versions.
Related errors
- could not read auth config
- Serde error: {error}
- Condition {condition_hash} not found
- Expected array or null for right-hand value of contains oper
- Expected number for {side}-hand value of comparison operatio
AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28).
Data as JSON: /api/errors/9807af8f64a5955d.
Report an issue: GitHub.