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 tokens

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Ensure the caller generates a one-time token first (ACLToken OneTimeToken endpoint) and passes its Secret field
  2. Add a non-empty check on the secret before invoking the lookup
  3. Fix the client/request so the secret is included in the body
  4. 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

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


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/6667a9030759a43f. Report an issue: GitHub.