hasura/graphql-engine · error · Error

JWT Authorization token source: Header name {header_name} no

Error message

JWT Authorization token source: Header name {header_name} not found.

What it means

The JWT is configured to be read from a custom HTTP header (`{header_name}`), but the incoming request does not contain that header.

Source

Thrown at v3/crates/auth/hasura-authn-jwt/src/jwt.rs:48

    ErrorDecodingAuthorizationHeader(jwt::errors::Error),
    #[error("`kid` (Key ID) header claim not found in the header")]
    KidHeaderNotFound,
    #[error("Expected the Hasura claims to be a String when `claimsFormat` is `stringifiedJson`")]
    ExpectedStringifiedJson,
    #[error("The default role is not present in the allowed roles")]
    DisallowedDefaultRole,
    #[error("The specified role is not present in the allowed roles")]
    DisallowedRole,
    #[error("Error while parsing the claims map entry: {claim_name} - {err}")]
    ParseClaimsMapEntryError {
        claim_name: String,
        err: serde_json::Error,
    },
    #[error("Expected string value for claim {claim_name}")]
    ClaimMustBeAString { claim_name: String },
    #[error("Required claim {claim_name} not found")]
    RequiredClaimNotFound { claim_name: String },
    #[error("JWT Authorization token source: Header name {header_name} not found.")]
    AuthorizationHeaderSourceNotFound { header_name: String },
    #[error("JWT Authorization token source: Cookie header not found")]
    CookieNotFound,
    #[error(
        "JWT Authorization token source: cookie name {cookie_name} not found in the Cookie header"
    )]
    CookieNameNotFound { cookie_name: String },
    #[error("Error in parsing the {header_name} header: {err}")]
    AuthorizationHeaderParseError { err: String, header_name: String },
    #[error("Error in parsing the Cookie header value: {err}")]
    CookieParseError { err: cookie::ParseError },
    #[error("Missing corresponding value for the cookie with cookie name: {cookie_name}")]
    MissingCookieValue { cookie_name: String },
    #[error("JWT validation error: {0}")]
    JWTValidationError(jwt::errors::Error),
    #[error("Internal Error - {0}")]
    Internal(#[from] InternalError),
}

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Verify the client sends the exact header name shown in {header_name}
  2. Correct the configured header name in JWT config if it's a typo
  3. Ensure proxies/gateways forward the custom header
  4. Add the custom header to allowed CORS headers if browser clients are used

Example fix

// before: client sends Authorization: Bearer <token> but config expects X-Auth-Token
// after: client sends X-Auth-Token: <token>
Defensive patterns

Strategy: validation

Validate before calling

const token = req.headers.get(config.jwtHeaderName);
if (!token) return unauthorized(`missing header ${config.jwtHeaderName}`);

Type guard

const hasHeader = (h: Headers, n: string): h is Headers & Record<n,string> => h.get(n) !== null;

Try / catch

Return 401 with the expected header name; no retry (client must resend with header).

Prevention

When it happens

Trigger: Auth mode is header-based JWT with a custom header name (e.g. `X-Auth-Token`) and the client sends the token elsewhere (Authorization header, cookie) or not at all.

Common situations: Client SDK not yet updated to send the custom header; header name typo in metadata vs. client; proxies/gateways stripping custom headers; CORS preflight not allowing the custom header.

Related errors


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