hashicorp/nomad · error
failed to extract claims from token: %w
Error message
failed to extract claims from token: %w
What it means
This error is returned by node_identity_endpoint.Get when the signed JWT parsed successfully but its claims could not be unmarshaled into a map. It calls UnsafeClaimsWithoutVerification, which decodes the payload without signature verification; failure means the payload JSON cannot be unmarshaled into map[string]any.
Source
Thrown at client/node_identity_endpoint.go:53
// be called before it has a JWT identity. Check we do not get an empty
// string before attempting to parse the token.
if identityToken == "" {
return errors.New("node does not have a JWT identity token")
}
// Parse the signed JWT token from the node identity and extract the claims
// into a map. This is done to avoid exposing the key material of the signed
// JWT token, but still results in all the claims which is perfect for
// debugging and introspection purposes.
parsedJWT, err := jwt.ParseSigned(identityToken)
if err != nil {
return fmt.Errorf("failed to parsed signed token: %w", err)
}
claims := make(map[string]any)
if err := parsedJWT.UnsafeClaimsWithoutVerification(&claims); err != nil {
return fmt.Errorf("failed to extract claims from token: %w", err)
}
resp.Claims = claims
return nil
}
func (n *NodeIdentity) Renew(args *structs.NodeIdentityRenewReq, _ *structs.NodeIdentityRenewResp) error {
// Check node write permissions.
if aclObj, err := n.c.ResolveToken(args.AuthToken); err != nil {
return err
} else if !aclObj.AllowNodeWrite() {
return structs.ErrPermissionDenied
}
// Store the node identity renewal request on the client, so it can be
// picked up at the next heartbeat.
n.c.identityForceRenewal.Store(true)View on GitHub (pinned to 482b49bf1a)
Solutions
- Regenerate the node identity token by restarting the Nomad client agent so the server issues a fresh, well-formed JWT
- Base64-decode the payload segment and confirm it is a JSON object with claim keys
- Ensure the token file contains a Nomad-issued identity token, not an arbitrary or foreign token
- Check Nomad agent/server version compatibility; older agents should not be fed tokens from newer formats
Example fix
// before: trusting any token file content
claims := make(map[string]any)
if err := parsedJWT.UnsafeClaimsWithoutVerification(&claims); err != nil {
return fmt.Errorf("failed to extract claims from token: %w", err)
}
// after: validate payload is a JSON object before decoding
payload, _ := parsedJWT.Payload()
var probe map[string]any
if err := json.Unmarshal(payload, &probe); err != nil {
return fmt.Errorf("identity token payload is not a JSON object; regenerate node identity token: %w", err)
} Defensive patterns
Strategy: validation
Validate before calling
payloadB64 := strings.Split(strings.TrimSpace(string(tokenBytes)), ".")[1]
payload, err := base64.RawURLEncoding.DecodeString(payloadB64)
if err != nil {
return fmt.Errorf("identity token payload not base64url: %w", err)
}
var probe map[string]any
if err := json.Unmarshal(payload, &probe); err != nil {
return fmt.Errorf("identity token payload is not a JSON object: %w", err)
} Type guard
func isJWTObjectPayload(token string) bool {
parts := strings.Split(token, ".")
if len(parts) != 3 {
return false
}
payload, err := base64.RawURLEncoding.DecodeString(parts[1])
if err != nil {
return false
}
var m map[string]any
return json.Unmarshal(payload, &m) == nil
} Try / catch
claims, err := nodeIdentityEndpoint.Get(ctx)
if err != nil {
if strings.Contains(err.Error(), "failed to extract claims") {
// token payload not a JSON object: regenerate via agent restart
return regenerateAndRetry(ctx)
}
return err
} Prevention
- Only consume tokens issued by the Nomad server's identity signing key
- Do not substitute foreign/OIDC tokens into the node identity file
- Validate token payloads in tooling before persisting them to disk
- Upgrade agents/servers together to avoid identity format drift
When it happens
Trigger: Calling the node identity RPC/endpoint when the JWT payload segment is not valid JSON, is not a JSON object (e.g. an array or string), or contains claims that cannot unmarshal into a map.
Common situations: A hand-crafted or corrupted token where the payload is not a JSON object; an opaque token issued by a non-Nomad identity provider placed in the token file; truncated base64 payload that decodes to invalid JSON.
Related errors
- failed to parsed signed token: %w
- failed to retrieve the ID token claims: %v
- invalid claims: %w
- no signed workload identity available
- node does not have a JWT identity token
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/c79e3f11a49b477e.
Report an issue: GitHub.