{"record":{"id":"84686cdbca614115","repo":"hashicorp/nomad","slug":"token-type-must-be-client-or-management","errorCode":null,"errorMessage":"token type must be client or management","messagePattern":"token type must be client or management","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/acl.go","lineNumber":778,"sourceCode":"\t// The human friendly name of an ACL token cannot exceed 256 characters.\n\tif len(a.Name) > maxTokenNameLength {\n\t\tmErr.Errors = append(mErr.Errors, errors.New(\"token name too long\"))\n\t}\n\n\t// The type of an ACL token must be set. An ACL token of type client must\n\t// have associated policies or roles, whereas a management token cannot be\n\t// associated with policies.\n\tswitch a.Type {\n\tcase ACLClientToken:\n\t\tif len(a.Policies) == 0 && len(a.Roles) == 0 {\n\t\t\tmErr.Errors = append(mErr.Errors, errors.New(\"client token missing policies or roles\"))\n\t\t}\n\tcase ACLManagementToken:\n\t\tif len(a.Policies) != 0 || len(a.Roles) != 0 {\n\t\t\tmErr.Errors = append(mErr.Errors, errors.New(\"management token cannot be associated with policies or roles\"))\n\t\t}\n\tdefault:\n\t\tmErr.Errors = append(mErr.Errors, errors.New(\"token type must be client or management\"))\n\t}\n\n\t// There are different validation rules depending on whether the ACL token\n\t// is being created or updated.\n\tswitch existing {\n\tcase nil:\n\t\tif a.ExpirationTTL < 0 {\n\t\t\tmErr.Errors = append(mErr.Errors,\n\t\t\t\tfmt.Errorf(\"token expiration TTL '%s' should not be negative\", a.ExpirationTTL))\n\t\t}\n\n\t\tif a.ExpirationTime != nil && !a.ExpirationTime.IsZero() {\n\n\t\t\tif a.CreateTime.After(*a.ExpirationTime) {\n\t\t\t\tmErr.Errors = append(mErr.Errors, errors.New(\"expiration time cannot be before create time\"))\n\t\t\t}\n\n\t\t\t// Create a time duration which details the time-til-expiry, so we can","sourceCodeStart":760,"sourceCodeEnd":796,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/acl.go#L760-L796","documentation":"Sentinel appended by ACLToken.Validate when a.Type matches neither ACLClientToken nor ACLManagementToken — the token's Type field was left empty or set to an invalid value.","triggerScenarios":"Upserting an ACLToken whose Type field is \"\", mistyped, or any value other than ACLClientToken/ACLManagementToken.","commonSituations":"Hand-constructed token structs missing the Type field; API clients sending lowercase/alternate casing; version changes where tokens were created without an explicit type.","solutions":["Set Type explicitly to \"client\" or \"management\" on the token","Validate the Type field before submitting the token request","Check for client-side code that omits zero-value enum fields"],"exampleFix":"// before\ntoken := &api.ACLToken{Name: \"ci\", Policies: []string{\"read\"}}\n// after\ntoken := &api.ACLToken{Name: \"ci\", Type: \"client\", Policies: []string{\"read\"}}","handlingStrategy":"validation","validationCode":"if token.Type != \"client\" && token.Type != \"management\" {\n    return fmt.Errorf(\"token type must be client or management, got %q\", token.Type)\n}","typeGuard":"func validTokenType(t string) bool {\n    return t == structs.ACLClientToken || t == structs.ACLManagementToken\n}","tryCatchPattern":"if err := token.Validate(minTTL, maxTTL, nil); err != nil {\n    if strings.Contains(err.Error(), \"token type must be client or management\") {\n        token.Type = structs.ACLClientToken\n        err = token.Validate(minTTL, maxTTL, nil)\n    }\n}","preventionTips":["Always set Type explicitly; the Go zero value \"\" is invalid","Use the structs.ACLClientToken/ACLManagementToken constants instead of raw strings","Validate tokens client-side before submission"],"tags":["nomad","acl","token","validation"],"backgroundTag":"input-validation-failed","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}