{"record":{"id":"e6d7aec3bc51b2f8","repo":"hashicorp/nomad","slug":"unable-to-find-configuration-for-consul-cluster-v","errorCode":null,"errorMessage":"unable to find configuration for consul cluster %v","messagePattern":"unable to find configuration for consul cluster (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/allocrunner/consul_hook.go","lineNumber":272,"sourceCode":"\nfunc (h *consulHook) getConsulToken(cluster string, req consul.JWTLoginRequest) (*consulapi.ACLToken, error) {\n\tclient, err := h.clientForCluster(cluster)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to retrieve Consul client for cluster %s: %v\", cluster, err)\n\t}\n\n\tt, err := client.DeriveTokenWithJWT(req)\n\tif err == nil {\n\t\terr = client.TokenPreflightCheck(h.shutdownCtx, t)\n\t}\n\n\treturn t, err\n}\n\nfunc (h *consulHook) clientForCluster(cluster string) (consul.Client, error) {\n\tconsulConf, ok := h.consulConfigs[cluster]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"unable to find configuration for consul cluster %v\", cluster)\n\t}\n\n\treturn h.consulClientConstructor(consulConf, h.logger)\n}\n\n// Postrun cleans up the Consul tokens after the tasks have exited.\nfunc (h *consulHook) Postrun() error {\n\treturn h.Destroy()\n}\n\n// Shutdown will get called when the client is gracefully stopping.\nfunc (h *consulHook) Shutdown() {\n\th.shutdownCancelFn()\n}\n\n// Destroy cleans up any remaining Consul tokens if the alloc is GC'd or fails\n// to restore after a client restart.\nfunc (h *consulHook) Destroy() error {","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/allocrunner/consul_hook.go#L254-L290","documentation":"clientForCluster looks up the requested Consul cluster in the hook's consulConfigs map; if absent it returns 'unable to find configuration for consul cluster %v'. This is the canonical internal lookup failure behind token derivation, and is also reachable from revokeTokens when cleaning up tokens for a cluster that no longer exists in config.","triggerScenarios":"getConsulToken called with a cluster name not in h.consulConfigs; revokeTokens (Postrun) attempts to revoke tokens for a cluster whose configuration was removed from the client between Prerun and Postrun.","commonSituations":"Client agent consul config changed/restarted between alloc start and stop; job references a cluster never configured on the client; multi-cluster naming mismatch after upgrading Nomad.","solutions":["Compare the cluster name in the message with the client agent's configured consul cluster names","Add the missing cluster to the client configuration and restart nomad before retrying allocations","If raised during Postrun/revokeTokens, accept token cleanup is best-effort: tokens will expire by TTL; fix config for future runs","Ensure all clients a job can be scheduled onto define every consul.cluster the job references"],"exampleFix":"// before: client agent missing the named cluster\nconsul { name = \"default\" }\n// after: define every cluster the jobs reference\nconsul { name = \"default\" }\nconsul { name = \"prod-east\" }","handlingStrategy":"validation","validationCode":"func clusterConfigured(consulConfigs map[string]consul.Config, cluster string) bool {\n    _, ok := consulConfigs[cluster]\n    return ok\n}\n// call before any token operation:\nif !clusterConfigured(h.consulConfigs, cluster) {\n    return fmt.Errorf(\"cluster %q not configured\", cluster)\n}","typeGuard":"func clusterConfigured(configs map[string]consul.Config, cluster string) bool {\n    _, ok := configs[cluster]\n    return ok\n}","tryCatchPattern":"if err := hook.Postrun(); err != nil {\n    if strings.Contains(err.Error(), \"unable to find configuration for consul cluster\") {\n        // best-effort revoke failed: log and continue; tokens expire via TTL\n    }\n}","preventionTips":["Keep cluster configs stable across agent restarts while allocs are live","Define every job-referenced cluster on all eligible clients","When removing a cluster from client config, drain its allocations first","Treat Postrun revocation failures as non-fatal; rely on token TTL expiry"],"tags":["consul","client-configuration","nomad","token-revocation"],"backgroundTag":"missing-cluster-configuration","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"}