{"record":{"id":"ae35b15d58101966","repo":"hashicorp/nomad","slug":"client-introduction-default-identity-ttl-must-be-g","errorCode":null,"errorMessage":"client_introduction.default_identity_ttl must be greater one","messagePattern":"client_introduction\\.default_identity_ttl must be greater one","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"command/agent/config.go","lineNumber":1269,"sourceCode":"\n// Validate performs validation on the ClientIntroduction configuration block to\n// ensure the values are set correctly for use by the server.\nfunc (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\"`","sourceCodeStart":1251,"sourceCodeEnd":1287,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/command/agent/config.go#L1251-L1287","documentation":"Within the client_introduction validation, `default_identity_ttl` must be at least 1 (interpreted as a duration; <1 is nonsensical). Validate() rejects values below 1 before checking max_identity_ttl relationships. This guarantees the agent never configures a zero or negative default identity lifetime.","triggerScenarios":"Config sets `client_introduction.default_identity_ttl` to 0 or a negative number (or the parsed duration is < 1) while the block is present, tripping `if c.DefaultIdentityTTL < 1`.","commonSituations":"Setting the TTL to 0 intending 'never expire' or 'inherit'; unit/test configs with placeholder values; unit confusion (seconds vs nanoseconds) making an intended positive value parse as near-zero.","solutions":["Set `default_identity_ttl` to a positive duration, e.g. \"1h\".","If you intended 'no expiry', use the maximum allowed TTL value instead of 0.","Verify the duration unit suffix is present in the config so the parsed value is not near-zero."],"exampleFix":"// before\nclient_introduction {\n  enforcement          = \"serve-and-mark\"\n  default_identity_ttl = 0\n}\n\n// after\nclient_introduction {\n  enforcement          = \"serve-and-mark\"\n  default_identity_ttl = \"1h\"\n}","handlingStrategy":"validation","validationCode":"if c := cfg.ClientIntroduction; c != nil && c.DefaultIdentityTTL < 1 {\n    return errors.New(\"client_introduction.default_identity_ttl must be >= 1\")\n}","typeGuard":"func validDefaultTTL(c *ClientIntroduction) bool { return c != nil && c.DefaultIdentityTTL >= 1 }","tryCatchPattern":null,"preventionTips":["Always include an explicit unit suffix (e.g. \"1h\") for TTL values.","Remember 0 does not mean 'unlimited'; use a large TTL for long-lived identities.","Validate TTLs in CI with the same checks the library performs."],"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"}