{"record":{"id":"49125e79c8135a5f","repo":"hashicorp/nomad","slug":"invalid-config-w","errorCode":null,"errorMessage":"invalid config: %w","messagePattern":"invalid config: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/acl.go","lineNumber":1444,"sourceCode":"func (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()\n}\n\n// Sanitize returns a copy of the ACLAuthMethod with any secrets redacted\nfunc (a *ACLAuthMethod) Sanitize() *ACLAuthMethod {\n\tif a == nil || a.Config == nil {\n\t\treturn a\n\t}\n\t// copy to ensure we do not mutate a pointer pulled directly out of state.\n\tclean := a.Copy()","sourceCodeStart":1426,"sourceCodeEnd":1462,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/acl.go#L1426-L1462","documentation":"ACLAuthMethod.Validate() wraps an error returned by a.Config.Validate(a.Type) with \"invalid config: %w\". The auth method's provider-specific Config (OIDC/JWT settings) failed its own validation, e.g. missing required URLs or client settings for the declared Type.","triggerScenarios":"For Type=OIDC: OIDCClientAssertion.Validate() failing or missing OIDCDiscoveryURL/OIDCClientID. For Type=JWT: no OIDCDiscoveryURL, no JWKSURL, and no JWTValidationPubKeys at all. The wrapped inner error names the exact missing/invalid field.","commonSituations":"Configuring OIDC but forgetting OIDCClientID or Discovery URL; deleting public keys/JWKS config when rotating secrets; copy-pasting a JWT config into an OIDC method or vice versa.","solutions":["Read the wrapped inner error (use %w/errors.Unwrap) and supply the named field, e.g. set OIDCDiscoveryURL and OIDCClientID.","If a client assertion is used, fix the fields its Validate() reports.","Match the config shape to the Type: OIDC needs discovery URL + client ID; JWT needs discovery URL OR JWKS URL OR public keys.","Verify the provider's discovery URL is reachable and correct (https, correct realm/tenant)."],"exampleFix":"// before\nam := &structs.ACLAuthMethod{Name: \"okta\", Type: \"OIDC\", Config: &structs.ACLAuthMethodConfig{}}\n// after\nam := &structs.ACLAuthMethod{Name: \"okta\", Type: \"OIDC\", Config: &structs.ACLAuthMethodConfig{\n  OIDCDiscoveryURL: \"https://idp.example.com/.well-known/openid-configuration\",\n  OIDCClientID:     \"nomad-client\",\n  BoundAudiences:   []string{\"nomad-client\"},\n}}","handlingStrategy":"validation","validationCode":"switch am.Type {\ncase \"OIDC\":\n\tif am.Config == nil || am.Config.OIDCDiscoveryURL == \"\" || am.Config.OIDCClientID == \"\" {\n\t\treturn errors.New(\"OIDC requires Config.OIDCDiscoveryURL and Config.OIDCClientID\")\n\t}\ncase \"JWT\":\n\tc := am.Config\n\tif c == nil || (c.OIDCDiscoveryURL == \"\" && c.JWKSURL == \"\" && len(c.JWTValidationPubKeys) == 0) {\n\t\treturn errors.New(\"JWT requires OIDCDiscoveryURL, JWKSURL, or JWTValidationPubKeys\")\n\t}\n}","typeGuard":"func hasJWTSource(c *structs.ACLAuthMethodConfig) bool {\n\treturn c != nil && (c.OIDCDiscoveryURL != \"\" || c.JWKSURL != \"\" || len(c.JWTValidationPubKeys) > 0)\n}","tryCatchPattern":"if err := am.Validate(minTTL, maxTTL); err != nil {\n\tvar inner error = errors.Unwrap(err) // walk multierror for 'invalid config:' wraps\n\treturn fmt.Errorf(\"fix auth-method config: %w\", err)\n}","preventionTips":["Always validate the wrapped inner error — it names the exact missing field","Keep OIDC (discovery URL + client ID) and JWT (key source) requirements separate","Re-check config after key rotations and provider URL changes"],"tags":["acl","validation","oidc","jwt","nomad"],"backgroundTag":"auth-method-config-missing","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"}