hashicorp/nomad · error

ACL token not found

Error message

ACL token not found

What it means

ErrTokenNotFound is a sentinel (nomad/structs/errors.go:56) returned when an ACL token (or equivalent credential) cannot be resolved for an RPC. It surfaces from token/role resolution paths (resolveTokenAndACL, ACL role handlers) and from the client ACL layer (client/acl.go:82) when a workload identity carries neither an ACLToken nor claims. The HTTP API maps it to a 403 response (command/agent/http.go:762).

Source

Thrown at nomad/structs/errors.go:56

	errRPCCodedErrorPrefix = "RPC Error:: "

	errDeploymentTerminalNoCancel    = "can't cancel terminal deployment"
	errDeploymentTerminalNoFail      = "can't fail terminal deployment"
	errDeploymentTerminalNoPause     = "can't pause terminal deployment"
	errDeploymentTerminalNoPromote   = "can't promote terminal deployment"
	errDeploymentTerminalNoResume    = "can't resume terminal deployment"
	errDeploymentTerminalNoUnblock   = "can't unblock terminal deployment"
	errDeploymentTerminalNoRun       = "can't run terminal deployment"
	errDeploymentTerminalNoSetHealth = "can't set health of allocations for a terminal deployment"
	errDeploymentRunningNoUnblock    = "can't unblock running deployment"
)

var (
	ErrNoLeader                   = errors.New(errNoLeader)
	ErrNotReadyForConsistentReads = errors.New(errNotReadyForConsistentReads)
	ErrNoRegionPath               = errors.New(errNoRegionPath)
	ErrTokenNotFound              = errors.New(errTokenNotFound)
	ErrTokenExpired               = errors.New(errTokenExpired)
	ErrTokenInvalid               = errors.New(errTokenInvalid)
	ErrPermissionDenied           = errors.New(errPermissionDenied)
	ErrJobRegistrationDisabled    = errors.New(errJobRegistrationDisabled)
	ErrNoNodeConn                 = errors.New(errNoNodeConn)
	ErrUnknownMethod              = errors.New(errUnknownMethod)
	ErrUnknownNomadVersion        = errors.New(errUnknownNomadVersion)
	ErrNodeLacksRpc               = errors.New(errNodeLacksRpc)
	ErrMissingAllocID             = errors.New(errMissingAllocID)
	ErrIncompatibleFiltering      = errors.New(errIncompatibleFiltering)
	ErrMalformedChooseParameter   = errors.New(errMalformedChooseParameter)

	// ErrResultPaginatorCreation is returned by list RPC handlers when the
	// result paginator cannot be built, for example when the server cannot
	// evaluate a requested filter expression. api.ResultPaginatorErrorContent
	// duplicates its message so the CLI can match it without importing structs.
	// Keep the two in sync.
	ErrResultPaginatorCreation = errors.New(errResultPaginatorCreation)

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Generate a new token with `nomad acl token create` (or via SSO/login for workload identities) and update the client's credentials
  2. Verify the token value is complete and correctly set (NOMAD_TOKEN env, -token flag, or agent config) — check for truncation or whitespace
  3. If using workload identities, ensure the job/task identity is configured so Claims are present, or that the ACL token was injected into the alloc
  4. Check `nomad acl token list` (with a management token) to confirm the token still exists and is not expired

Example fix

// before
client.SetToken(os.Getenv("NOMAD_TOKEN")) // stale/revoked token
// after
token := os.Getenv("NOMAD_TOKEN")
if token == "" {
    token = fetchNewTokenFromVault() // re-issue from secure store
}
client.SetToken(token)
Defensive patterns

Strategy: try-catch

Validate before calling

// verify the token resolves before making calls
_, _, err := client.ACL().GetToken(tokenID)
if err != nil {
    return fmt.Errorf("token %q is invalid or deleted; re-issue credentials", tokenID)
}

Type guard

func isTokenNotFound(err error) bool {
    return errors.Is(err, structs.ErrTokenNotFound) || strings.Contains(err.Error(), structs.ErrTokenNotFound.Error())
}

Try / catch

resp, err := client.System().ListMembers()
if err != nil {
    if isTokenNotFound(err) {
        // HTTP 403 path: refresh credentials and retry once
        client.SetToken(rotateToken())
        resp, err = client.System().ListMembers()
    }
    if err != nil {
        return err
    }
}

Prevention

When it happens

Trigger: Passing an `X-Nomad-Token` whose SecretID doesn't exist (expired/deleted token); empty or missing token where ACLs are enabled; client RPC with a workload identity lacking both ACLToken and Claims; referencing a token that was revoked or purged from state store.

Common situations: Stale NOMAD_TOKEN env var or CLI config after token rotation; CI/CD using a token deleted by policy; upgrading workloads to workload identities while the old ACL token was revoked; copy-pasting a truncated secret ID.

Related errors


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