{"record":{"id":"0d962a86e28f2d23","repo":"grafana/k6","slug":"aggregation-wait-period-is-not-allowed-to-be-zero","errorCode":null,"errorMessage":"aggregation wait period is not allowed to be zero","messagePattern":"aggregation wait period is not allowed to be zero","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"output/cloud/expv2/collect.go","lineNumber":76,"sourceCode":"\t// map, we can probably use a simple slice (or even an array!) as a ring buffer to store the\n\t// aggregation buckets. This should save us a some time, since it would make the lookups and WaitPeriod\n\t// checks basically O(1). And even if for some reason there are occasional metrics with past times that\n\t// don't fit in the chosen ring buffer size, we could just send them along to the buffer unaggregated\n\ttimeBuckets map[int64]map[metrics.TimeSeries]metricValue\n}\n\nfunc newCollector(aggrPeriod, waitPeriod time.Duration) (*collector, error) {\n\tif aggrPeriod == 0 {\n\t\treturn nil, errors.New(\"aggregation period is not allowed to be zero\")\n\t}\n\tif aggrPeriod != aggrPeriod.Truncate(time.Second) {\n\t\treturn nil, errors.New(\"aggregation period is not allowed to have sub-second precision\")\n\t}\n\tif waitPeriod == 0 {\n\t\t// TODO: we could simplify the expiring logic\n\t\t// just having an internal static logic.\n\t\t// Like skip only not closed buckets bucketEnd > now.\n\t\treturn nil, errors.New(\"aggregation wait period is not allowed to be zero\")\n\t}\n\tif waitPeriod != waitPeriod.Truncate(time.Second) {\n\t\treturn nil, errors.New(\"aggregation wait period is not allowed to have sub-second precision\")\n\t}\n\treturn &collector{\n\t\tbq:                bucketQ{},\n\t\tnowFunc:           time.Now,\n\t\ttimeBuckets:       make(map[int64]map[metrics.TimeSeries]metricValue),\n\t\taggregationPeriod: aggrPeriod,\n\t\twaitPeriod:        waitPeriod,\n\t}, nil\n}\n\n// CollectSamples drain the buffer and collect all the samples.\nfunc (c *collector) CollectSamples(containers []metrics.SampleContainer) {\n\t// Distribute all newly buffered samples into related buckets\n\tfor _, sampleContainer := range containers {\n\t\tsamples := sampleContainer.GetSamples()","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/output/cloud/expv2/collect.go#L58-L94","documentation":"Returned by newCollector (output/cloud/expv2/collect.go:72-77) when the aggregation wait period is zero. The wait period is how long a closed time bucket is kept open for late-arriving samples before it is flushed (collect.go:164 expires buckets older than now-waitPeriod); zero wait would drop every bucket's stragglers and the expiring logic relies on a non-zero window, hence the guard (with the in-code TODO about simplifying the expiring logic).","triggerScenarios":"Setting K6_CLOUD_AGGREGATION_WAIT_PERIOD=0s (env var feeding expv2 Config.AggregationWaitPeriod, default 5s), or programmatic construction with AggregationWaitPeriod: types.NullDurationFrom(0). Fails at Output.Start as 'failed to initialize the samples collector'.","commonSituations":"Trying to minimize end-to-end latency of Cloud metric delivery by removing the wait window; tuning both aggregation knobs together and setting one to zero.","solutions":["Set the wait period to a positive whole-second value, e.g. 5s (default) or 1s for lower latency at the cost of more dropped late samples"],"exampleFix":"# before\nK6_CLOUD_AGGREGATION_WAIT_PERIOD=0s k6 run -o cloud script.js\n\n# after\nK6_CLOUD_AGGREGATION_WAIT_PERIOD=1s k6 run -o cloud script.js","handlingStrategy":"validation","validationCode":"# shell: guard the wait period\nW=\"${K6_CLOUD_AGGREGATION_WAIT_PERIOD:-5s}\"\ncase \"$W\" in 0s) echo \"wait period must be >= 1s\"; exit 1;; esac\nexport K6_CLOUD_AGGREGATION_WAIT_PERIOD=\"$W\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep K6_CLOUD_AGGREGATION_WAIT_PERIOD at 1s or above; 0 would flush buckets before late samples land","When lowering it to 1s for latency, expect slightly more samples to fall outside their bucket"],"tags":["cloud-output","aggregation","config","k6"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}