hashicorp/nomad · error
failed to parsed signed token: %w
Error message
failed to parsed signed token: %w
What it means
This error is returned by node_identity_endpoint.Get when parsing the client's signed JWT identity token fails. The endpoint parses the JWT solely to expose its claims for debugging/introspection, without verifying the signature. If the token bytes are not a well-formed JWS compact serialization, go-jose's jwt.ParseSigned fails and the underlying error is wrapped here.
Source
Thrown at client/node_identity_endpoint.go:47
return structs.ErrPermissionDenied
}
identityToken := n.c.nodeIdentityToken()
// The client could be upgraded before all the servers allowing this API to
// 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() {View on GitHub (pinned to 482b49bf1a)
Solutions
- Inspect the node identity token file and confirm it is a three-segment dot-separated JWT (header.payload.signature)
- Delete the corrupted/empty token file and restart the Nomad agent so it regenerates a fresh signed token
- Verify file permissions and that no external process truncates the token file while the agent is running
- Check agent logs for the underlying go-jose parse error to confirm whether the token is malformed vs merely unverifiable
Example fix
// before: reading a stale/empty token file directly
identityToken := string(badTokenBytes)
parsedJWT, err := jwt.ParseSigned(identityToken)
// after: guard for empty/malformed token before parsing
identityToken := strings.TrimSpace(string(badTokenBytes))
if identityToken == "" || strings.Count(identityToken, ".") != 2 {
return fmt.Errorf("node identity token missing or malformed; restart agent to regenerate")
}
parsedJWT, err := jwt.ParseSigned(identityToken) Defensive patterns
Strategy: validation
Validate before calling
token := strings.TrimSpace(string(tokenBytes))
if token == "" || strings.Count(token, ".") != 2 {
return fmt.Errorf("node identity token missing or not a JWT compact token")
}
if _, err := base64.RawURLEncoding.DecodeString(strings.Split(token, ".")[0]); err != nil {
return fmt.Errorf("identity token header segment not valid base64url: %w", err)
} Type guard
func isCompactJWT(s string) bool {
parts := strings.Split(s, ".")
if len(parts) != 3 {
return false
}
for _, p := range parts {
if _, err := base64.RawURLEncoding.DecodeString(p); err != nil {
return false
}
}
return true
} Try / catch
claims, err := nodeIdentityEndpoint.Get(ctx)
if err != nil {
if strings.Contains(err.Error(), "failed to parsed signed token") {
// regenerate token: restart agent or re-fetch identity
return refreshIdentityToken(ctx)
}
return err
} Prevention
- Never hand-edit or truncate the node identity token file
- Ensure the token file is fully written before clients read it (use atomic file writes)
- Restart the Nomad client agent to regenerate tokens after corruption
- Monitor for zero-byte token files in the client data/secret dir
When it happens
Trigger: Calling the Node identity RPC (Client.NodeIdentity or the agent's /v1/node/identity HTTP endpoint) when the identity token file on disk is empty, truncated, corrupted, or not in JWT compact form.
Common situations: A leftover or partially written node_identity_token file from a failed startup; manual edits to the token file; Nomad versions where the token file is missing content; disk corruption or truncated file after crash; mounting an empty secret/configMap path over the token file.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- node does not have a JWT identity token
- failed to extract claims from token: %w
- node identity claims missing node pool
- failed to sign node identity claims: %v
- no signed workload identity available
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/844c6e1bc2b4f6c5.
Report an issue: GitHub.