hashicorp/nomad · error
acl token lookup failed: missing accessor id
Error message
acl token lookup failed: missing accessor id
What it means
A validation error from StateStore.ACLTokenByAccessorID: the caller passed an empty accessor ID string. The store refuses the lookup up-front rather than doing a pointless table scan that would match nothing. It is a caller-input bug, not a state problem.
Source
Thrown at nomad/state/state_store.go:6436
txn := s.db.WriteTxnMsgT(msgType, index)
defer txn.Abort()
// Delete the tokens
for _, id := range ids {
if _, err := txn.DeleteAll("acl_token", "id", id); err != nil {
return fmt.Errorf("deleting acl token failed: %v", err)
}
}
if err := txn.Insert("index", &IndexEntry{"acl_token", index}); err != nil {
return fmt.Errorf("index update failed: %v", err)
}
return txn.Commit()
}
// ACLTokenByAccessorID is used to lookup a token by accessor ID
func (s *StateStore) ACLTokenByAccessorID(ws memdb.WatchSet, id string) (*structs.ACLToken, error) {
if id == "" {
return nil, fmt.Errorf("acl token lookup failed: missing accessor id")
}
txn := s.db.ReadTxn()
watchCh, existing, err := txn.FirstWatch("acl_token", "id", id)
if err != nil {
return nil, fmt.Errorf("acl token lookup failed: %v", err)
}
ws.Add(watchCh)
// If the existing token is nil, this indicates it does not exist in state.
if existing == nil {
return nil, nil
}
// Assert the token type which allows us to perform additional work on the
// token that is needed before returning the call.
token := existing.(*structs.ACLToken)View on GitHub (pinned to 482b49bf1a)
Solutions
- Check that the accessor ID is non-empty before calling the store (strings.TrimSpace + len check).
- At the API layer, reject requests with a missing token early with a 400/permission-denied instead of reaching the state store.
- Audit call sites so empty IDs short-circuit with a domain error rather than the store sentinel.
Example fix
// before
token, err := store.ACLTokenByAccessorID(ws, req.SecretToken)
// after
if req.SecretToken == "" {
return structs.NewErrRPCCoded(400, "missing token secret ID")
}
token, err := store.ACLTokenByAccessorID(ws, req.SecretToken) Defensive patterns
Strategy: validation
Validate before calling
func canLookupByAccessor(id string) bool {
return strings.TrimSpace(id) != ""
}
// before calling:
// if !canLookupByAccessor(accessorID) { return errors.New("missing accessor id") } Type guard
func hasAccessorID(t *struct.ACLToken) bool {
return t != nil && t.AccessorID != ""
} Try / catch
if accessorID == "" {
return fmt.Errorf("acl token lookup skipped: accessor id required")
}
token, err := store.ACLTokenByAccessorID(ws, accessorID)
if err != nil { return err } Prevention
- Always check token strings for emptiness (and whitespace) at the API edge
- Reject token-less requests early with 400/403 instead of hitting the store
- Trim X-Nomad-Token header values before lookup
- Add tests covering the empty-ID path of your handlers
When it happens
Trigger: Calling ACLTokenByAccessorID with "" — e.g., resolving a token from an HTTP request whose X-Nomad-Token header is empty, or code that did not check a struct field before lookup.
Common situations: Clients sending requests without a token header; config where a token variable was never set; fuzzer/test callers omitting the ID; handlers that strip empty strings after trimming whitespace.
Related errors
- acl token lookup failed: missing secret id
- ACL policy not found
- ACL role not found
- detected corrupted token within the state store: missing rol
- node ids missing
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/fd410437e7fed447.
Report an issue: GitHub.