{"record":{"id":"2517f08d9934b2bd","repo":"nats-io/nats-server","slug":"duplicates-window-can-not-be-negative","errorCode":null,"errorMessage":"duplicates window can not be negative","messagePattern":"duplicates window can not be negative","errorType":"error_code","errorClass":"JSStreamInvalidConfigError","httpStatus":null,"severity":"error","filePath":"server/stream.go","lineNumber":1975,"sourceCode":"\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\n\t\t} else {\n\t\t\tcfg.Duplicates = maxWindow\n\t\t}\n\t}\n\tif cfg.Duplicates < 0 {\n\t\treturn StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf(\"duplicates window can not be negative\"))\n\t}\n\t// Check that duplicates is not larger then age if set.\n\tif cfg.MaxAge != 0 && cfg.Duplicates > cfg.MaxAge {\n\t\treturn StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf(\"duplicates window can not be larger then max age\"))\n\t}\n\tif lim.Duplicates > 0 && cfg.Duplicates > lim.Duplicates {\n\t\treturn StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf(\"duplicates window can not be larger then server limit of %v\",\n\t\t\tlim.Duplicates.String()))\n\t}\n\tif cfg.Duplicates > 0 && cfg.Duplicates < 100*time.Millisecond {\n\t\treturn StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf(\"duplicates window needs to be >= 100ms\"))\n\t}\n\n\tif cfg.DenyPurge && cfg.AllowRollup {\n\t\treturn StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf(\"roll-ups require the purge permission\"))\n\t}\n\n\t// Counter is not compatible with some settings.","sourceCodeStart":1957,"sourceCodeEnd":1993,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/stream.go#L1957-L1993","documentation":"JetStream stream config validation rejects a negative Duplicates window (time to cache recently published messages for duplicate detection). The library validates this in StreamConfig validation (server/stream.go) before creating or updating a stream, because a negative duration is meaningless. It is returned as a JSStreamInvalidConfigError so the client can correct the config.","triggerScenarios":"Creating or updating a stream via JetStream API (AddStream/UpdateStream or jetstream.CreateStream) with StreamConfig.Duplicates set to a negative time.Duration value, e.g. -1 * time.Second.","commonSituations":"Config parsed from JSON/YAML where a negative number was entered; code computing the window from a clock offset or subtraction that underflows; unmarshalling user-supplied API payloads directly into StreamConfig without pre-validation.","solutions":["Set StreamConfig.Duplicates to a non-negative duration (e.g. 2*time.Minute, the server default).","If unset is desired, leave Duplicates at 0 so the server applies its default instead of a negative value.","Sanitize externally supplied config: clamp Duplicates with max(0, value) before calling the API.","Check code that computes the window via subtraction for accidental negation."],"exampleFix":"// before\n cfg := jetstream.StreamConfig{Name: \"ORDERS\", Duplicates: -time.Second}\n// after\n cfg := jetstream.StreamConfig{Name: \"ORDERS\", Duplicates: 2 * time.Minute}","handlingStrategy":"validation","validationCode":"if cfg.Duplicates < 0 {\n    return fmt.Errorf(\"duplicates window must be >= 0, got %s\", cfg.Duplicates)\n}","typeGuard":null,"tryCatchPattern":"var scErr *jetstream.JSApiError\nif _, err := js.CreateStream(ctx, cfg); errors.As(err, &scErr) && strings.Contains(scErr.Description, \"duplicates window can not be negative\") {\n    cfg.Duplicates = 0 // let server apply default\n    _, err = js.CreateStream(ctx, cfg)\n}","preventionTips":["Never set negative durations in StreamConfig; use 0 for 'server default'.","Clamp user/externally supplied Duplicates values with max(0, v).","Audit duration math (subtraction) that feeds Duplicates for underflow."],"tags":["jetstream","stream-config","validation","nats"],"backgroundTag":"invalid-stream-config","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}