{"record":{"id":"37e1392de20b1e60","repo":"vitessio/vitess","slug":"buffer-window-must-be-buffer-max-failover-d","errorCode":null,"errorMessage":"--buffer-window must be <= --buffer-max-failover-duration: %v vs. %v","messagePattern":"--buffer-window must be <= --buffer-max-failover-duration: (.+?) vs\\. (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtgate/buffer/flags.go","lineNumber":70,"sourceCode":"\tutils.SetFlagIntVar(fs, &bufferSize, \"buffer-size\", 1000, \"Maximum number of buffered requests in flight (across all ongoing failovers).\")\n\tutils.SetFlagDurationVar(fs, &bufferMaxFailoverDuration, \"buffer-max-failover-duration\", 20*time.Second, \"Stop buffering completely if a failover takes longer than this duration.\")\n\tutils.SetFlagDurationVar(fs, &bufferMinTimeBetweenFailovers, \"buffer-min-time-between-failovers\", 1*time.Minute, \"Minimum time between the end of a failover and the start of the next one (tracked per shard). Faster consecutive failovers will not trigger buffering.\")\n\n\tutils.SetFlagIntVar(fs, &bufferDrainConcurrency, \"buffer-drain-concurrency\", 1, \"Maximum number of requests retried simultaneously. More concurrency will increase the load on the PRIMARY vttablet when draining the buffer.\")\n\tutils.SetFlagStringVar(fs, &bufferKeyspaceShards, \"buffer-keyspace-shards\", \"\", \"If not empty, limit buffering to these entries (comma separated). Entry format: keyspace or keyspace/shard. Requires --enable_buffer=true.\")\n}\n\nfunc init() {\n\tservenv.OnParseFor(\"vtgate\", registerFlags)\n\tservenv.OnParseFor(\"vtcombo\", registerFlags)\n}\n\nfunc verifyFlags() error {\n\tif bufferWindow < 1*time.Second {\n\t\treturn fmt.Errorf(\"--buffer-window must be >= 1s (specified value: %v)\", bufferWindow)\n\t}\n\tif bufferWindow > bufferMaxFailoverDuration {\n\t\treturn fmt.Errorf(\"--buffer-window must be <= --buffer-max-failover-duration: %v vs. %v\", bufferWindow, bufferMaxFailoverDuration)\n\t}\n\tif bufferSize < 1 {\n\t\treturn fmt.Errorf(\"--buffer-size must be >= 1 (specified value: %d)\", bufferSize)\n\t}\n\tif bufferMinTimeBetweenFailovers < 1*time.Second {\n\t\treturn fmt.Errorf(\"--buffer-min-time-between-failovers must be >= 1s (specified value: %v)\", bufferMinTimeBetweenFailovers)\n\t}\n\n\tif bufferDrainConcurrency < 1 {\n\t\treturn fmt.Errorf(\"--buffer-drain-concurrency must be >= 1 (specified value: %d)\", bufferDrainConcurrency)\n\t}\n\n\tif bufferKeyspaceShards != \"\" && !bufferEnabled {\n\t\treturn fmt.Errorf(\"--buffer-keyspace-shards=%v also requires that --enable_buffer is set\", bufferKeyspaceShards)\n\t}\n\tif bufferEnabled && bufferEnabledDryRun && bufferKeyspaceShards == \"\" {\n\t\treturn errors.New(\"both the dry-run mode and actual buffering is enabled. To avoid ambiguity, keyspaces and shards for actual buffering must be explicitly listed in --buffer-keyspace-shards\")\n\t}","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtgate/buffer/flags.go#L52-L88","documentation":"verifyFlags enforces that the buffering window (--buffer-window) is not larger than the maximum failover duration (--buffer-max-failover-duration). Buffering stops after the max failover duration, so a window exceeding it is contradictory configuration and vtgate rejects it at startup.","triggerScenarios":"Starting vtgate with --buffer-window greater than --buffer-max-failover-duration, e.g. --buffer-window=60s --buffer-max-failover-duration=30s.","commonSituations":"Increasing --buffer-window after an incident without revisiting --buffer-max-failover-duration; copying flag sets from different environments; typo swapping the two values.","solutions":["Lower --buffer-window so it is <= --buffer-max-failover-duration","Or raise --buffer-max-failover-duration (note it also caps how long buffering runs)","Also check that --buffer-max-failover-duration >= 1s, since it must satisfy its own validation"],"exampleFix":"// before\nvtgate --buffer-window=60s --buffer-max-failover-duration=30s\n// after\nvtgate --buffer-window=30s --buffer-max-failover-duration=60s","handlingStrategy":"validation","validationCode":"if bufferWindow > bufferMaxFailoverDuration {\n    return fmt.Errorf(\"--buffer-window (%v) must be <= --buffer-max-failover-duration (%v)\", bufferWindow, bufferMaxFailoverDuration)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat --buffer-window and --buffer-max-failover-duration as a pair and set them together","Validate the combined flag set in CI before rollout","Document the invariant window <= max-failover-duration in runbooks"],"tags":["vtgate","buffering","flag-validation","configuration"],"backgroundTag":"invalid-flag-value","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}