{"record":{"id":"a7503cea8b50c97a","repo":"hashicorp/nomad","slug":"invalid-token-locality-s","errorCode":null,"errorMessage":"invalid token locality '%s'","messagePattern":"invalid token locality '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/acl.go","lineNumber":1435,"sourceCode":"\t\ta.TokenNameFormat = helper.Merge(a.TokenNameFormat, b.TokenNameFormat)\n\t\ta.MaxTokenTTL = helper.Merge(a.MaxTokenTTL, b.MaxTokenTTL)\n\t\ta.Config = helper.Merge(a.Config, b.Config)\n\t}\n}\n\n// Validate returns an error is the ACLAuthMethod is invalid.\n//\n// TODO revisit possible other validity conditions in the future\nfunc (a *ACLAuthMethod) Validate(minTTL, maxTTL time.Duration) error {\n\tvar mErr multierror.Error\n\n\tif !ValidACLAuthMethod.MatchString(a.Name) {\n\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"invalid name '%s'\", a.Name))\n\t}\n\n\tif !slices.Contains([]string{ACLAuthMethodTokenLocalityLocal, ACLAuthMethodTokenLocalityGlobal}, a.TokenLocality) {\n\t\tmErr.Errors = append(\n\t\t\tmErr.Errors, fmt.Errorf(\"invalid token locality '%s'\", a.TokenLocality))\n\t}\n\n\tif !slices.Contains(ValidACLAuthMethodTypes, a.Type) {\n\t\tmErr.Errors = append(\n\t\t\tmErr.Errors, fmt.Errorf(\"invalid token type '%s'\", a.Type))\n\t}\n\n\tif err := a.Config.Validate(a.Type); err != nil {\n\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\"invalid config: %w\", err))\n\t}\n\n\tif minTTL > a.MaxTokenTTL || a.MaxTokenTTL > maxTTL {\n\t\tmErr.Errors = append(mErr.Errors, fmt.Errorf(\n\t\t\t\"invalid MaxTokenTTL value '%s' (should be between %s and %s)\",\n\t\t\ta.MaxTokenTTL.String(), minTTL.String(), maxTTL.String()))\n\t}\n\n\treturn mErr.ErrorOrNil()","sourceCodeStart":1417,"sourceCodeEnd":1453,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/acl.go#L1417-L1453","documentation":"ACLAuthMethod.Validate() rejects TokenLocality because it is not one of 'local' (ACLAuthMethodTokenLocalityLocal) or 'global' (ACLAuthMethodTokenLocalityGlobal). This controls whether tokens issued via the method work only on the local cluster or across federated clusters.","triggerScenarios":"Upserting an ACL auth method with TokenLocality set to any string other than exactly \"local\" or \"global\", including \"\" (empty), \"Local\", or \"cluster\".","commonSituations":"Case-sensitivity mistakes ('Local'); copying config from Consul which uses different locality vocabulary; forgetting the field in hand-written JSON payloads.","solutions":["Set TokenLocality to exactly \"local\" or \"global\" (lowercase).","Use the exported constants structs.ACLAuthMethodTokenLocalityLocal / ...Global in Go code instead of string literals.","If the field is absent in JSON, set it explicitly in the payload."],"exampleFix":"// before\nam := &structs.ACLAuthMethod{Name: \"okta\", Type: \"OIDC\", TokenLocality: \"Local\"}\n// after\nam := &structs.ACLAuthMethod{Name: \"okta\", Type: \"OIDC\", TokenLocality: structs.ACLAuthMethodTokenLocalityLocal}","handlingStrategy":"validation","validationCode":"if am.TokenLocality != \"local\" && am.TokenLocality != \"global\" {\n\treturn fmt.Errorf(\"TokenLocality must be local|global, got %q\", am.TokenLocality)\n}","typeGuard":"func validTokenLocality(v string) bool { return v == \"local\" || v == \"global\" }","tryCatchPattern":"if err := am.Validate(minTTL, maxTTL); err != nil {\n\tif strings.Contains(err.Error(), \"invalid token locality\") {\n\t\tam.TokenLocality = \"local\" // safe default, revalidate\n\t}\n\treturn err\n}","preventionTips":["Use structs.ACLAuthMethodTokenLocalityLocal/Global constants, never literals","Locality is lowercase — watch for 'Local'/'GLOBAL' from YAML configs","Set the field explicitly in every JSON payload"],"tags":["acl","validation","nomad"],"backgroundTag":"invalid-enum-value","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"}