hashicorp/nomad · warning
one-time token lookup failed: missing secret
Error message
one-time token lookup failed: missing secret
What it means
OneTimeTokenBySecret refuses to query the state store when the provided secret is the empty string. Unlike other lookups that return nil,nil for missing values, an empty secret is treated as a caller error and raises immediately.
Source
Thrown at nomad/state/state_store.go:6713
return txn.Commit()
}
// oneTimeTokensExpiredTxn returns an iterator over all expired one-time tokens
func (s *StateStore) oneTimeTokensExpiredTxn(txn *txn, ws memdb.WatchSet, timestamp time.Time) (memdb.ResultIterator, error) {
iter, err := txn.Get("one_time_token", "id")
if err != nil {
return nil, fmt.Errorf("one-time token lookup failed: %v", err)
}
ws.Add(iter.WatchCh())
iter = memdb.NewFilterIterator(iter, expiredOneTimeTokenFilter(timestamp))
return iter, nil
}
// OneTimeTokenBySecret is used to lookup a token by secret
func (s *StateStore) OneTimeTokenBySecret(ws memdb.WatchSet, secret string) (*structs.OneTimeToken, error) {
if secret == "" {
return nil, fmt.Errorf("one-time token lookup failed: missing secret")
}
txn := s.db.ReadTxn()
watchCh, existing, err := txn.FirstWatch("one_time_token", "secret", secret)
if err != nil {
return nil, fmt.Errorf("one-time token lookup failed: %v", err)
}
ws.Add(watchCh)
if existing != nil {
return existing.(*structs.OneTimeToken), nil
}
return nil, nil
}
// expiredOneTimeTokenFilter returns a filter function that returns only
// expired one-time tokensView on GitHub (pinned to 482b49bf1a)
Solutions
- Ensure the caller generates a one-time token first (ACLToken OneTimeToken endpoint) and passes its Secret field
- Add a non-empty check on the secret before invoking the lookup
- Fix the client/request so the secret is included in the body
- Check for version skew between client and server API fields
Example fix
// before
ott, err := state.OneTimeTokenBySecret(ws, token.Secret)
// after
if token == nil || token.Secret == "" {
return fmt.Errorf("no one-time token secret supplied")
}
ott, err := state.OneTimeTokenBySecret(ws, token.Secret) Defensive patterns
Strategy: validation
Validate before calling
if secret == "" {
return fmt.Errorf("one-time token secret must be provided before lookup")
} Type guard
func hasOneTimeSecret(t *structs.OneTimeToken) bool { return t != nil && t.Secret != "" } Try / catch
ott, err := state.OneTimeTokenBySecret(ws, secret)
if err != nil && strings.Contains(err.Error(), "missing secret") {
return structs.NewErrRPCCoded(400, "one-time token secret required")
} Prevention
- Always fetch a one-time token from the API before presenting its secret for decryption
- Validate request bodies for required secret fields at the RPC boundary
- Check client/server version skew on OneTimeToken fields
When it happens
Trigger: Calling state store OneTimeTokenBySecret (or the HTTP endpoint that resolves an one-time token) with an empty/absent secret, e.g. a request body missing the OneTimeToken secret field.
Common situations: Automation submitting an empty one-time-token secret for variable decryption; a client that failed to fetch the one-time token first; older clients/workload drivers omitting the field.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- job_submission requires a namespace
- job_submission requires a jobID
- validating volume %q against state failed: %v
- unknown new job status %q
- deleting node pool %q is not allowed
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/6667a9030759a43f.
Report an issue: GitHub.