{"record":{"id":"2fbbdea2c417083a","repo":"nats-io/nats-server","slug":"max-age-can-not-be-negative","errorCode":null,"errorMessage":"max age can not be negative","messagePattern":"max age can not be negative","errorType":"error_code","errorClass":"JSStreamInvalidConfigError","httpStatus":null,"severity":"error","filePath":"server/stream.go","lineNumber":1951,"sourceCode":"\t\tif pedantic && cfg.MaxBytes < -1 {\n\t\t\treturn StreamConfig{}, NewJSPedanticError(fmt.Errorf(\"max_bytes must be set to -1\"))\n\t\t}\n\t\tcfg.MaxBytes = -1\n\t}\n\tif cfg.MaxMsgSize == 0 || cfg.MaxMsgSize < -1 {\n\t\tif pedantic && cfg.MaxMsgSize < -1 {\n\t\t\treturn StreamConfig{}, NewJSPedanticError(fmt.Errorf(\"max_msg_size must be set to -1\"))\n\t\t}\n\t\tcfg.MaxMsgSize = -1\n\t}\n\tif cfg.MaxConsumers == 0 || cfg.MaxConsumers < -1 {\n\t\tif pedantic && cfg.MaxConsumers < -1 {\n\t\t\treturn StreamConfig{}, NewJSPedanticError(fmt.Errorf(\"max_consumers must be set to -1\"))\n\t\t}\n\t\tcfg.MaxConsumers = -1\n\t}\n\tif cfg.MaxAge < 0 {\n\t\treturn StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf(\"max age can not be negative\"))\n\t}\n\tif cfg.MaxAge != 0 && cfg.MaxAge < 100*time.Millisecond {\n\t\treturn StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf(\"max age needs to be >= 100ms\"))\n\t}\n\n\tif cfg.Duplicates == 0 && cfg.Mirror == nil && len(cfg.Sources) == 0 {\n\t\tmaxWindow := StreamDefaultDuplicatesWindow\n\t\tif lim.Duplicates > 0 && maxWindow > lim.Duplicates {\n\t\t\tif pedantic {\n\t\t\t\treturn StreamConfig{}, NewJSPedanticError(fmt.Errorf(\"duplicate window limits are higher than current limits\"))\n\t\t\t}\n\t\t\tmaxWindow = lim.Duplicates\n\t\t}\n\t\tif cfg.MaxAge != 0 && cfg.MaxAge < maxWindow {\n\t\t\tif pedantic {\n\t\t\t\treturn StreamConfig{}, NewJSPedanticError(fmt.Errorf(\"duplicate window cannot be bigger than max age\"))\n\t\t\t}\n\t\t\tcfg.Duplicates = cfg.MaxAge","sourceCodeStart":1933,"sourceCodeEnd":1969,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/stream.go#L1933-L1969","documentation":"JetStream rejects a stream config whose MaxAge (max message retention duration) is negative. MaxAge must be zero (use stream default) or a positive duration; this is a hard JSStreamInvalidConfigError regardless of pedantic mode.","triggerScenarios":"Stream create/update with cfg.MaxAge < 0, e.g. time.Duration computed as -30*time.Minute or an unparsed/wrong-unit value yielding a negative duration. server/stream.go:1951.","commonSituations":"Retention computed from a deadline in the past (now - expiry); config parsing where a string like '-1h' was passed; arithmetic on time.Duration in the wrong unit producing overflow/negative values.","solutions":["Fix the duration computation so MaxAge is non-negative (e.g. 30*time.Minute)","Set MaxAge to 0 to use the server default retention window","Clamp with a guard: if maxAge < 0 { maxAge = 0 } before submitting"],"exampleFix":"// before\nMaxAge: time.Until(deadline) // deadline already passed -> negative\n// after\nif d := time.Until(deadline); d > 0 { cfg.MaxAge = d } else { cfg.MaxAge = 0 }","handlingStrategy":"validation","validationCode":"if cfg.MaxAge < 0 {\n    return fmt.Errorf(\"MaxAge cannot be negative; got %v\", cfg.MaxAge)\n}","typeGuard":null,"tryCatchPattern":"if err != nil {\n    var apiErr *nats.APIError\n    if errors.As(err, &apiErr) && apiErr.ErrorCode == nats.ErrorCodeJetStreamInvalidStreamConfig {\n        // log the raw MaxAge value for diagnosis, then fix or clamp\n        cfg.MaxAge = 0\n        err = createStream(cfg)\n    }\n}","preventionTips":["Clamp durations to >= 0 after any time computation","Guard against 'deadline in the past' producing negative time.Until results","Use typed duration parsing helpers instead of raw string-to-duration casts"],"tags":["jetstream","stream-config","validation","duration"],"backgroundTag":"jetstream-invalid-stream-config","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}