{"record":{"id":"8210da8befd359f6","repo":"hashicorp/nomad","slug":"client-introduction-max-identity-ttl-must-be-great","errorCode":null,"errorMessage":"client_introduction.max_identity_ttl must be greater one","messagePattern":"client_introduction\\.max_identity_ttl must be greater one","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"command/agent/config.go","lineNumber":1272,"sourceCode":"func (c *ClientIntroduction) Validate() error {\n\n\tif c == nil {\n\t\treturn nil\n\t}\n\n\tif c.Enforcement == \"\" {\n\t\treturn errors.New(\"client_introduction.enforcement must be set\")\n\t}\n\tif !slices.Contains(ClientIntroductionEnforcementValues, c.Enforcement) {\n\t\treturn fmt.Errorf(\"client_introduction.enforcement must be one of %v\",\n\t\t\tClientIntroductionEnforcementValues)\n\t}\n\n\tif c.DefaultIdentityTTL < 1 {\n\t\treturn errors.New(\"client_introduction.default_identity_ttl must be greater one\")\n\t}\n\tif c.MaxIdentityTTL < 1 {\n\t\treturn errors.New(\"client_introduction.max_identity_ttl must be greater one\")\n\t}\n\tif c.MaxIdentityTTL < c.DefaultIdentityTTL {\n\t\treturn errors.New(\"client_introduction.max_identity_ttl must be greater than default_identity_ttl\")\n\t}\n\n\treturn nil\n}\n\n// ServerJoin is used in both clients and servers to bootstrap connections to\n// servers\ntype ServerJoin struct {\n\t// StartJoin is a list of addresses to attempt to join when the\n\t// agent starts. If Serf is unable to communicate with any of these\n\t// addresses, then the agent will error and exit.\n\tStartJoin []string `hcl:\"start_join\"`\n\n\t// RetryJoin is a list of addresses to join with retry enabled, or a single\n\t// value to find multiple servers using go-discover syntax.","sourceCodeStart":1254,"sourceCodeEnd":1290,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/command/agent/config.go#L1254-L1290","documentation":"client_introduction validation also requires `max_identity_ttl` to be at least 1, mirroring the default TTL check. A zero or negative maximum identity lifetime is invalid because the agent could never issue any valid identity. This check runs before the max>=default comparison.","triggerScenarios":"Config sets `client_introduction.max_identity_ttl` to 0 or a negative value (or parses to < 1) while enforcement is valid and default_identity_ttl passes its own check.","commonSituations":"Setting max_ttl = 0 intending 'unlimited'; copy/paste dropping the value; unit mismatch making the intended duration parse as zero.","solutions":["Set `max_identity_ttl` to a positive duration, e.g. \"24h\".","Ensure max_identity_ttl >= default_identity_ttl so the subsequent check also passes.","If 0 was meant to signal 'unlimited', use the largest supported duration instead."],"exampleFix":"// before\nclient_introduction {\n  enforcement          = \"serve-and-mark\"\n  default_identity_ttl = \"1h\"\n  max_identity_ttl     = 0\n}\n\n// after\nclient_introduction {\n  enforcement          = \"serve-and-mark\"\n  default_identity_ttl = \"1h\"\n  max_identity_ttl     = \"24h\"\n}","handlingStrategy":"validation","validationCode":"if c := cfg.ClientIntroduction; c != nil && c.MaxIdentityTTL < 1 {\n    return errors.New(\"client_introduction.max_identity_ttl must be >= 1\")\n}","typeGuard":"func validMaxTTL(c *ClientIntroduction) bool { return c != nil && c.MaxIdentityTTL >= 1 }","tryCatchPattern":null,"preventionTips":["Set max_identity_ttl alongside default_identity_ttl as a pair.","Avoid 0/negative values; 0 is not 'unlimited'.","Keep duration units explicit in generated configs."],"tags":["config-validation","ttl","client-introduction"],"backgroundTag":"invalid-config-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"}