{"record":{"id":"08990ce69303847b","repo":"jaegertracing/jaeger","slug":"ttl-must-be-a-non-negative-duration","errorCode":null,"errorMessage":"ttl must be a non-negative duration","messagePattern":"ttl must be a non-negative duration","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/v2/clickhouse/config.go","lineNumber":83,"sourceCode":"// DefaultConfiguration returns the configuration a ClickHouse backend starts from\n// before the user's own settings are unmarshaled over it.\nfunc DefaultConfiguration() Configuration {\n\treturn Configuration{\n\t\tProtocol:                      defaultProtocol,\n\t\tDatabase:                      defaultDatabase,\n\t\tDefaultSearchDepth:            defaultSearchDepth,\n\t\tMaxSearchDepth:                defaultMaxSearchDepth,\n\t\tAttributeMetadataCacheTTL:     defaultAttributeMetadataCacheTTL,\n\t\tAttributeMetadataCacheMaxSize: defaultAttributeMetadataCacheMaxSize,\n\t}\n}\n\nfunc (cfg *Configuration) Validate() error {\n\tif _, err := govalidator.ValidateStruct(cfg); err != nil {\n\t\treturn err\n\t}\n\tif cfg.TTL < 0 {\n\t\treturn errors.New(\"ttl must be a non-negative duration\")\n\t}\n\tif cfg.TTL > 0 && cfg.TTL%time.Second != 0 {\n\t\treturn errors.New(\"ttl must be a whole number of seconds\")\n\t}\n\t// A search depth of zero would make every trace search return nothing, and a\n\t// negative one is meaningless, so reject both rather than querying with them.\n\tif cfg.DefaultSearchDepth <= 0 {\n\t\treturn errors.New(\"default_search_depth must be a positive number\")\n\t}\n\tif cfg.MaxSearchDepth <= 0 {\n\t\treturn errors.New(\"max_search_depth must be a positive number\")\n\t}\n\tif cfg.AttributeMetadataCacheTTL < 0 {\n\t\treturn errors.New(\"attribute_metadata_cache_ttl must be a non-negative duration\")\n\t}\n\tif cfg.AttributeMetadataCacheMaxSize < 0 {\n\t\treturn errors.New(\"attribute_metadata_cache_max_size must be a non-negative number\")\n\t}","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/internal/storage/v2/clickhouse/config.go#L65-L101","documentation":"ClickHouse Configuration.Validate returns this error when the TTL field is negative. TTL controls data retention and must be a non-negative duration; a negative value is meaningless for ClickHouse table settings.","triggerScenarios":"Loading a ClickHouse storage configuration whose TTL is set below zero, then calling Validate (directly or via factory creation).","commonSituations":"Hand-edited config files with negative durations; misparsing duration strings from env/flags into negative numbers; copy-paste of a value with a stray minus sign.","solutions":["Set TTL to a non-negative duration (e.g. \"720h\" or 0 to disable expiry)","Fix the source of the value (env var, YAML, CLI flag) so it cannot be negative","Ensure govalidator tags plus this Validate check are run before the writer/reader are created"],"exampleFix":"// before\nttl: -1h\n// after\nttl: 720h0m0s","handlingStrategy":"validation","validationCode":"if cfg.TTL < 0 {\n    return errors.New(\"ttl must be a non-negative duration\")\n}","typeGuard":"func validTTL(d time.Duration) bool { return d >= 0 }","tryCatchPattern":"if err := cfg.Validate(); err != nil {\n    if strings.Contains(err.Error(), \"ttl must be a non-negative duration\") {\n        cfg.TTL = defaultTTL // or fail startup with a clear message\n    }\n}","preventionTips":["Validate configuration before starting the storage factory","Never hand-write negative durations in config files","Bind config through typed duration parsing that rejects negatives"],"tags":["clickhouse","configuration","ttl","jaeger"],"backgroundTag":"invalid-config-value","analyzedSha":"806f4447841ecdb60519f408b004a599d515f437","analyzedAt":"2026-09-01T02:39:22.140Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}