{"record":{"id":"c000d4759f3ee70f","repo":"nats-io/nats-server","slug":"duplicates-window-needs-to-be-100ms","errorCode":null,"errorMessage":"duplicates window needs to be >= 100ms","messagePattern":"duplicates window needs to be >= 100ms","errorType":"error_code","errorClass":"JSStreamInvalidConfigError","httpStatus":null,"severity":"error","filePath":"server/stream.go","lineNumber":1986,"sourceCode":"\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.\n\tif cfg.AllowMsgCounter {\n\t\tif cfg.Discard == DiscardNew {\n\t\t\treturn StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf(\"counter stream cannot use discard new\"))\n\t\t}\n\t\tif cfg.AllowMsgTTL {\n\t\t\treturn StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf(\"counter stream cannot use message TTLs\"))\n\t\t}\n\t\tif cfg.AllowMsgSchedules {\n\t\t\treturn StreamConfig{}, NewJSStreamInvalidConfigError(fmt.Errorf(\"counter stream cannot use message schedules\"))\n\t\t}\n\t\tif cfg.Retention != LimitsPolicy {","sourceCodeStart":1968,"sourceCodeEnd":2004,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/stream.go#L1968-L2004","documentation":"A non-zero Duplicates window smaller than 100ms is rejected because duplicate detection granularity below 100ms is unreliable and adds cache churn without benefit. Validation in server/stream.go enforces a 100ms floor on any positive Duplicates value. Returned as a JSStreamInvalidConfigError.","triggerScenarios":"AddStream/UpdateStream with Duplicates set to a positive duration < 100ms, e.g. Duplicates: 10*time.Millisecond (note: exactly 0 is allowed and means 'use server default').","commonSituations":"Unit-test configs with tiny windows to 'keep memory low'; converting millisecond config fields to time.Duration incorrectly; assuming sub-100ms windows are permitted like other durations.","solutions":["Set Duplicates to at least 100ms (typically 2 minutes is fine).","Set Duplicates to 0 to use the server default instead of a tiny value.","If tests need fast settings, use >= 100ms or omit Duplicates.","Round any computed window up to 100ms minimum before applying it."],"exampleFix":"// before\n StreamConfig{Name: \"TEST\", Duplicates: 10 * time.Millisecond}\n// after\n StreamConfig{Name: \"TEST\", Duplicates: 100 * time.Millisecond}","handlingStrategy":"validation","validationCode":"if cfg.Duplicates > 0 && cfg.Duplicates < 100*time.Millisecond {\n    cfg.Duplicates = 100 * time.Millisecond\n}","typeGuard":null,"tryCatchPattern":"var scErr *jetstream.JSApiError\nif _, err := js.CreateStream(ctx, cfg); errors.As(err, &scErr) && strings.Contains(scErr.Description, \"duplicates window needs to be >= 100ms\") {\n    cfg.Duplicates = 0 // use server default\n    _, err = js.CreateStream(ctx, cfg)\n}","preventionTips":["Treat 100ms as the minimum; use 0 for default rather than tiny values.","In tests, omit Duplicates instead of setting milliseconds-scale windows.","Round computed windows up to the 100ms floor."],"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"}