{"record":{"id":"a102878497716f32","repo":"hashicorp/nomad","slug":"failed-to-retrieve-signed-workload-identity-w","errorCode":null,"errorMessage":"failed to retrieve signed workload identity: %w","messagePattern":"failed to retrieve signed workload identity: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/allocrunner/taskrunner/vault_hook.go","lineNumber":377,"sourceCode":"\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn \"\", 0, ctx.Err()\n\t\tcase <-timer.C:\n\t\t}\n\t}\n}\n\n// deriveVaultTokenJWT returns a Vault ACL token using JWT auth login.\nfunc (h *vaultHook) deriveVaultTokenJWT(ctx context.Context) (string, int, error) {\n\t// Retrieve signed identity.\n\tsigned, err := h.widmgr.Get(structs.WIHandle{\n\t\tIdentityName:       h.widName,\n\t\tWorkloadIdentifier: h.task.Name,\n\t\tWorkloadType:       structs.WorkloadTypeTask,\n\t})\n\tif err != nil {\n\t\treturn \"\", 0, structs.NewRecoverableError(\n\t\t\tfmt.Errorf(\"failed to retrieve signed workload identity: %w\", err),\n\t\t\ttrue,\n\t\t)\n\t}\n\tif signed == nil {\n\t\treturn \"\", 0, structs.NewRecoverableError(\n\t\t\terrors.New(\"no signed workload identity available\"),\n\t\t\tfalse,\n\t\t)\n\t}\n\n\trole := h.vaultConfig.Role\n\tif h.vaultBlock.Role != \"\" {\n\t\trole = h.vaultBlock.Role\n\t}\n\n\t// Derive Vault token with signed identity.\n\ttoken, renewable, leaseDuration, err := h.client.DeriveTokenWithJWT(ctx, vaultclient.JWTLoginRequest{\n\t\tJWT:       signed.JWT,","sourceCodeStart":359,"sourceCodeEnd":395,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/allocrunner/taskrunner/vault_hook.go#L359-L395","documentation":"When the allocrunner's vault hook uses workload identity (JWT-based Vault auth) via deriveVaultTokenJWT, it requests a signed workload identity from the alloc runner's identity RPC. If the RPC fails, the error is wrapped and marked recoverable so the taskrunner can retry token derivation.","triggerScenarios":"deriveVaultToken calls deriveVaultTokenJWT, which invokes the signed-identity getter with the task's wid name; the underlying client RPC (consul/vault identity signing endpoint) returns an error — server unreachable, signing not enabled, or transient backend failure.","commonSituations":"Nomad server that does not yet support workload-identity signing (version mismatch); Vault/Consul integration misconfigured on the server; transient network partitions between client and server during allocation start.","solutions":["Retry — the error is already marked recoverable, so transient failures should resolve on retry","Verify Nomad server version supports signed workload identities for tasks","Check server config for vault/workload identity settings (jwt validation, signing keys)","Inspect server logs for the identity-signing RPC failure to find the root cause"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// precheck server support before enabling WI-based vault\n// ensure server version >= feature introduction and vault WI stanza configured","typeGuard":null,"tryCatchPattern":"token, err := deriveVaultToken(ctx)\nif err != nil {\n    var rec *structs.RecoverableError\n    if errors.As(err, &rec) && rec.IsRecoverable() {\n        return retryWithBackoff(ctx, deriveVaultToken)\n    }\n    return err\n}","preventionTips":["Keep Nomad client and server on compatible versions","Configure and verify Vault workload-identity signing on servers before rollout","Monitor client-server connectivity; retries mask only transient faults","Test WI auth in staging with the same server topology"],"tags":["nomad","vault","workload-identity","rpc"],"backgroundTag":"workload-identity-signing-failed","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"}