hashicorp/nomad · error
management token cannot be associated with policies or roles
Error message
management token cannot be associated with policies or roles
What it means
Appended by ACLToken.Validate when a management-type token has policies or roles attached. Management tokens implicitly grant all privileges and cannot be scoped; only client tokens carry explicit policy/role links.
Source
Thrown at nomad/structs/acl.go:775
func (a *ACLToken) Validate(minTTL, maxTTL time.Duration, existing *ACLToken) error {
var mErr multierror.Error
// The human friendly name of an ACL token cannot exceed 256 characters.
if len(a.Name) > maxTokenNameLength {
mErr.Errors = append(mErr.Errors, errors.New("token name too long"))
}
// The type of an ACL token must be set. An ACL token of type client must
// have associated policies or roles, whereas a management token cannot be
// associated with policies.
switch a.Type {
case ACLClientToken:
if len(a.Policies) == 0 && len(a.Roles) == 0 {
mErr.Errors = append(mErr.Errors, errors.New("client token missing policies or roles"))
}
case ACLManagementToken:
if len(a.Policies) != 0 || len(a.Roles) != 0 {
mErr.Errors = append(mErr.Errors, errors.New("management token cannot be associated with policies or roles"))
}
default:
mErr.Errors = append(mErr.Errors, errors.New("token type must be client or management"))
}
// There are different validation rules depending on whether the ACL token
// is being created or updated.
switch existing {
case nil:
if a.ExpirationTTL < 0 {
mErr.Errors = append(mErr.Errors,
fmt.Errorf("token expiration TTL '%s' should not be negative", a.ExpirationTTL))
}
if a.ExpirationTime != nil && !a.ExpirationTime.IsZero() {
if a.CreateTime.After(*a.ExpirationTime) {
mErr.Errors = append(mErr.Errors, errors.New("expiration time cannot be before create time"))View on GitHub (pinned to 482b49bf1a)
Solutions
- Set Policies and Roles to empty lists when Type is management
- Keep Type as client if you need the attached policies/roles
- Strip the policy/role fields when converting a token to management type
Example fix
// before
token.Type = "management" // Policies still populated
// after
token.Type = "management"
token.Policies = []string{}
token.Roles = []string{} Defensive patterns
Strategy: validation
Validate before calling
if token.Type == "management" && (len(token.Policies) != 0 || len(token.Roles) != 0) {
return errors.New("management tokens cannot have policies or roles")
} Type guard
func managementTokenUnscoped(t *structs.ACLToken) bool {
return t.Type != structs.ACLManagementToken || (len(t.Policies) == 0 && len(t.Roles) == 0)
} Try / catch
if err := token.Validate(minTTL, maxTTL, nil); err != nil {
if strings.Contains(err.Error(), "management token cannot be associated") {
token.Policies, token.Roles = nil, nil
err = token.Validate(minTTL, maxTTL, nil)
}
} Prevention
- Clear Policies/Roles when setting Type to management
- Never flip a client token to management without stripping its grants
- Prefer client tokens with policies; use management tokens sparingly
When it happens
Trigger: Upserting an ACLToken with Type == "management" while Policies or Roles is non-empty.
Common situations: Cloning an existing client token and changing only its Type to management while keeping the old policy/role lists; scripts that copy token structs and flip the type field.
Related errors
- token name too long
- client token missing policies or roles
- token type must be client or management
- expiration time cannot be before create time
- cannot toggle global mode
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/d26c1dfd62a4139b.
Report an issue: GitHub.