{"record":{"id":"8407fb3743aa6563","repo":"hashicorp/nomad","slug":"acl-token-not-found-or-invalid-workload-identity","errorCode":null,"errorMessage":"ACL token not found or invalid workload identity: %v","messagePattern":"ACL token not found or invalid workload identity: (.+?)","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"command/agent/http.go","lineNumber":420,"sourceCode":"\t\ts.listener.Close()\n\t\t<-s.listenerCh // block until http.Serve has returned.\n\t}\n}\n\n// ResolveToken extracts the ACL token secret ID from the request and\n// translates it into an ACL object. Returns nil if ACLs are disabled.\nfunc (s *HTTPServer) ResolveToken(req *http.Request) (*acl.ACL, error) {\n\tvar secret string\n\ts.parseToken(req, &secret)\n\n\tvar aclObj *acl.ACL\n\tvar err error\n\n\tif srv := s.agent.Server(); srv != nil {\n\t\tr := &structs.GenericRequest{}\n\t\tr.AuthToken = secret\n\t\tif authErr := srv.Authenticate(nil, r); authErr != nil {\n\t\t\treturn nil, fmt.Errorf(\"ACL token not found or invalid workload identity: %v\", authErr)\n\t\t}\n\n\t\taclObj, err = srv.ResolveACL(r)\n\t} else {\n\t\t// Not a Server, so use the Client for token resolution. Note\n\t\t// this gets forwarded to a server with AllowStale = true if\n\t\t// the local ACL cache TTL has expired (30s by default)\n\t\taclObj, err = s.agent.Client().ResolveToken(secret)\n\t}\n\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to resolve ACL token: %v\", err)\n\t}\n\n\treturn aclObj, nil\n}\n\n// registerHandlers is used to attach our handlers to the mux","sourceCodeStart":402,"sourceCodeEnd":438,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/command/agent/http.go#L402-L438","documentation":"Returned by the HTTP server's ResolveToken (command/agent/http.go:420) when a request presents a secret (ACL token secretID or workload identity) that srv.Authenticate rejects on the server. The bearer token does not correspond to a known ACL token or valid workload identity on the resolved server, so the request is rejected.","triggerScenarios":"Any authenticated API request (agent self/reload/host, jobs parse) with Authorization: Bearer or X-Nomad-Token whose secretID was deleted/expired, belongs to a different cluster/region, or is a workload identity JWT the server cannot validate while ACLs are enabled.","commonSituations":"Token rotation with clients caching old secretIDs; pointing clients at the wrong cluster; stale NOMAD_TOKEN in env/CI; truncated tokens from copy-paste; misconfigured workload identities in job templates.","solutions":["Verify the token exists on this cluster: `nomad acl token self -secret=<id>`.","Create a new token with `nomad acl token create` and update X-Nomad-Token / NOMAD_TOKEN.","Check NOMAD_ADDR/NOMAD_REGION — you may be authenticating against a different cluster.","For workload identities, confirm the identity name and that the JWT is passed unmodified.","Purge stale credentials from CI/env and re-authenticate."],"exampleFix":"// before\nexport NOMAD_TOKEN=stale-deleted-secret-id\nnomad agent-info\n// after: verify and use a live token\nnomad acl token list\nexport NOMAD_TOKEN=<valid-secret-id>\nnomad agent-info","handlingStrategy":"validation","validationCode":"out, err := exec.Command(\"nomad\", \"acl\", \"token\", \"self\", \"-secret\", secret).CombinedOutput()\nif err != nil {\n    return fmt.Errorf(\"token invalid on this cluster: %s\", out)\n}","typeGuard":null,"tryCatchPattern":"if err != nil {\n    if strings.Contains(err.Error(), \"ACL token not found or invalid workload identity\") {\n        // mint a new token via nomad acl token create and retry once\n    }\n}","preventionTips":["Fetch tokens programmatically instead of hard-coding.","Rotate clients' stored secretIDs whenever tokens are deleted.","Verify NOMAD_ADDR/NOMAD_REGION point at the intended cluster.","Use SDK auth helpers so the token is transmitted unmodified."],"tags":["acl","authentication","token","nomad"],"backgroundTag":"acl-token-invalid","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}