hashicorp/nomad · error
JWT login did not return a token
Error message
JWT login did not return a token
What it means
Raised by DeriveTokenWithJWT in client/vaultclient/vaultclient.go when Vault returns a Secret but its Auth block is nil, meaning the login endpoint did not authenticate the caller or return a token. In Vault, a nil Auth on a login response typically indicates the request was accepted but no auth lease was created (e.g. an error swallowed by the server or a login endpoint that returned a non-auth response).
Source
Thrown at client/vaultclient/vaultclient.go:165
if req.Namespace != "" {
cc.SetNamespace(req.Namespace)
}
jwtLoginPath := fmt.Sprintf("auth/%s/login", c.config.JWTAuthBackendPath)
s, err := cc.Logical().WriteWithContext(ctx, jwtLoginPath,
map[string]any{
"role": req.Role,
"jwt": req.JWT,
},
)
if err != nil {
return "", false, 0, fmt.Errorf("failed to login with JWT: %v", err)
}
if s == nil {
return "", false, 0, errors.New("JWT login returned an empty secret")
}
if s.Auth == nil {
return "", false, 0, errors.New("JWT login did not return a token")
}
for _, w := range s.Warnings {
c.logger.Warn("JWT login warning", "warning", w)
}
return s.Auth.ClientToken, s.Auth.Renewable, s.Auth.LeaseDuration, nil
}
func (c *vaultClient) Renew(ctx context.Context, token string, lease int) (duration time.Duration, err error) {
cc, err := c.Clone()
if err != nil {
return 0, err
}
cc.SetToken(token)
res, err := cc.Auth().Token().RenewSelfWithContext(ctx, lease)
if err != nil {View on GitHub (pinned to 482b49bf1a)
Solutions
- Verify the JWT and role are valid: run `vault write auth/<mount>/login role=<role> jwt=<token>` manually against Vault
- Check the configured JWTAuthBackendPath matches the enabled auth mount in Vault
- Inspect Vault audit logs for the login request to see why no token was issued
- Check Vault token quota/policy settings that might suppress token creation
- Upgrade Nomad/Vault pair; older Vault versions returned empty auth on some login failures
Example fix
// before
// Vault returns secret with nil Auth; code proceeds and panics on s.Auth.ClientToken
token := s.Auth.ClientToken
// after
if s == nil { return "", false, 0, errors.New("JWT login returned an empty secret") }
if s.Auth == nil { return "", false, 0, errors.New("JWT login did not return a token") }
token := s.Auth.ClientToken Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight: verify JWT and role resolve to a token outside Nomad: // vault write auth/<mount>/login role=<role> jwt=<jwt> -> must return auth.client_token
Type guard
func secretHasToken(s *vaultapi.Secret) bool {
return s != nil && s.Auth != nil && s.Auth.ClientToken != ""
} Try / catch
token, _, _, err := client.DeriveTokenWithJWT(ctx, req)
if err != nil {
if strings.Contains(err.Error(), "JWT login did not return a token") {
// inspect role/mount config; refresh JWT; retry after fix
}
return err
} Prevention
- Keep the Vault JWT/OIDC role bound to the claims your workload actually presents
- Confirm JWTAuthBackendPath matches the enabled Vault auth mount
- Check Vault token quotas and policies before rollout so token creation cannot be silently suppressed
When it happens
Trigger: JWT auth backend returning a 200 with no auth block (e.g. role misconfiguration, policies denying token creation); hitting the wrong login path so a generic endpoint responds instead of the JWT login; Vault token quotas or policy preventing token issuance while still returning a response object.
Common situations: Wrong JWTAuthBackendPath configured in Nomad; Vault JWT/OIDC role not bound to the presented JWT claims; Vault 'token' namespace or cluster issues where auth creation silently fails; expired/invalid JWTs in Vault versions that return 200 with empty auth.
Related errors
- no signed workload identity available
- JWT login returned an empty secret
- failed to login with JWT: %v
- [✘] Could not retrieve JWT accessor: %w
- [✘] Could not enable JWT credential backend: %w
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/991c7ebe34a8f110.
Report an issue: GitHub.