hashicorp/nomad · error
unable to find token for workload %q and identity %q
Error message
unable to find token for workload %q and identity %q
What it means
WIDMgr.Get is the synchronous accessor tasks use to obtain a signed identity token; it returns an error if no token is cached for the given WIHandle. By design every identity should have a token by the time Get is called, so this signals a lifecycle bug or premature access.
Source
Thrown at client/widmgr/widmgr.go:150
}
go m.renew()
return nil
}
// Get retrieves the latest signed identity or returns an error. It must be
// called after Run and does not block.
//
// For retrieving tokens which might be renewed callers should use Watch
// instead to avoid missing new tokens retrieved by Run between Get and Watch
// calls.
func (m *WIDMgr) Get(id structs.WIHandle) (*structs.SignedWorkloadIdentity, error) {
token := m.get(id)
if token == nil {
// This is an error as every identity should have a token by the time Get
// is called.
return nil, fmt.Errorf("unable to find token for workload %q and identity %q", id.WorkloadIdentifier, id.IdentityName)
}
return token, nil
}
func (m *WIDMgr) get(id structs.WIHandle) *structs.SignedWorkloadIdentity {
m.lastTokenLock.RLock()
defer m.lastTokenLock.RUnlock()
return m.lastToken[id]
}
// Watch returns a channel that sends new signed identities until it is closed
// due to shutdown. Must be called after Run.
//
// The caller must call the returned func to stop watching and ensure the
// watched id actually exists, otherwise the channel never returns a result.
func (m *WIDMgr) Watch(id structs.WIHandle) (<-chan *structs.SignedWorkloadIdentity, func()) {View on GitHub (pinned to 482b49bf1a)
Solutions
- Ensure Run() completed and signing succeeded before calling Get.
- Verify the WIHandle matches exactly the workload identifier and identity name that were requested.
- Check logs for earlier 'failed to fetch signed identities' errors indicating the manager never got tokens.
- Restart the task/agent so identities are re-requested and cached.
Example fix
// before
tok, err := widMgr.Get(structs.WIHandle{WorkloadIdentifier: tgName, IdentityName: "vault_token"})
// after
handle := alloc.TaskServicesWIHandleForIdentity(tgName, "vault_token") // derive from alloc, not hand-built
tok, err := widMgr.Get(handle)
if err != nil {
return fmt.Errorf("identity not yet available: %w", err)
} Defensive patterns
Strategy: type-guard
Validate before calling
// ensure the manager is ready before Get
if !widMgr.Ready() { // or wait on a ready channel
return fmt.Errorf("widmgr not initialized")
} Type guard
func tokenAvailable(m *WIDMgr, id structs.WIHandle) bool { return m.get(id) != nil } Try / catch
tok, err := widMgr.Get(handle)
if err != nil {
if strings.Contains(err.Error(), "unable to find token") {
// wait for renewal/signing, then retry once
time.Sleep(backoff)
tok, err = widMgr.Get(handle)
}
if err != nil { return err }
} Prevention
- Build WIHandle from the allocation, never by hand
- Wait for Run()/initial signing to complete before Get
- Check for prior signing failures in logs
When it happens
Trigger: Calling Get with a WIHandle whose WorkloadIdentifier/IdentityName was never requested (or whose token was fetched but not yet stored), or after signing failed and Run's refresh never populated the manager.
Common situations: Task hook calling Get before Run/getInitialIdentities completed; identity name typo or handle built from wrong workload; signing previously failed so nothing was cached; restart where state DB lost the token.
Related errors
- no signed workload identity available
- error getting signed identity for task %s: %v
- error getting signed identity for service %s: %v
- failed to retrieve signed workload identity: %w
- no identities to sign
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/06b28c324a6d7cf9.
Report an issue: GitHub.