hashicorp/nomad · error
failed to login with JWT: %v
Error message
failed to login with JWT: %v
What it means
DeriveTokenWithJWT wraps any error returned by Vault's JWT auth login (client.auth.JWT().Login) with this message. It means the Vault login call itself failed — the underlying error carries the real cause (network, 400/403, unknown role, etc.). The function derives a workload token by exchanging a JWT for a Vault secret.
Source
Thrown at client/vaultclient/vaultclient.go:159
return "", false, 0, err
}
// Make sure the login request is not passing any token and that we're using
// the expected namespace to login
cc.SetToken("")
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 {View on GitHub (pinned to 482b49bf1a)
Solutions
- Read the wrapped %v cause to identify the underlying failure (network vs auth rejection).
- Verify the Vault JWT auth role name in the request matches a role configured on the Vault auth method.
- Check that the JWT is valid and unexpired (decode it or test with 'vault write auth/jwt/login role=... jwt=...').
- Verify Vault address, TLS, and namespace settings in the Nomad Vault config.
- Confirm the JWT auth method is enabled at the expected mount path in Vault.
Example fix
// before role := "old-role" // removed in Vault // after role := "nomad-workloads" // role that exists on the Vault jwt auth method
Defensive patterns
Strategy: try-catch
Validate before calling
// before deriving: ensure inputs are sane
if req.JWT == "" || req.Role == "" {
return fmt.Errorf("JWT and role are required before Vault login")
} Type guard
func hasVaultAuth(s *api.Secret) bool { return s != nil && s.Auth != nil && s.Auth.ClientToken != "" } Try / catch
token, _, _, err := vc.DeriveTokenWithJWT(req)
if err != nil {
if strings.Contains(err.Error(), "failed to login with JWT") {
logger.Error("vault jwt login failed", "cause", err, "role", req.Role)
// check role name, JWT expiry, Vault reachability before retrying
}
return err
} Prevention
- Validate role name against Vault config before login
- Check JWT expiry (exp claim) before deriving
- Monitor Vault reachability/health endpoint
- Pin Vault auth mount path and role names in config management
When it happens
Trigger: Calling DeriveTokenWithJWT when the Vault server is unreachable, the auth method/role 'req.Role' does not exist or mismatches the JWT, the JWT is expired/invalid, or the mount path is wrong — any non-nil error from the login call.
Common situations: Vault role renamed or deleted after agent config was written; expired workload JWT; Vault agent/auth mount disabled; TLS or network misconfiguration between Nomad client and Vault; wrong Vault address/namespace in config.
Related errors
- no signed workload identity available
- no auth method config or client assertion
- missing login token
- JWT login returned an empty secret
- JWT login did not return a token
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/0280eba16079d837.
Report an issue: GitHub.