{"record":{"id":"0fcccd5b16e1ee63","repo":"grafana/k6","slug":"aggregation-period-is-not-allowed-to-be-zero","errorCode":null,"errorMessage":"aggregation period is not allowed to be zero","messagePattern":"aggregation period is not allowed to be zero","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"output/cloud/expv2/collect.go","lineNumber":67,"sourceCode":"\ntype collector struct {\n\tbq      bucketQ\n\tnowFunc func() time.Time\n\n\taggregationPeriod time.Duration\n\twaitPeriod        time.Duration\n\n\t// we should no longer have to handle metrics that have times long in the past. So instead of a\n\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,","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/output/cloud/expv2/collect.go#L49-L85","documentation":"Returned by newCollector (output/cloud/expv2/collect.go:66-68), the constructor of the cloud output's aggregation collector. The aggregation period is the size of the time buckets used to batch metric samples before pushing them to the Cloud v2 ingestion endpoint; a zero period would make bucketID division by zero (collect.go:156 divides UnixNano by the period), so it is rejected. Config reaches it from expv2 Config.AggregationPeriod, settable via K6_CLOUD_AGGREGATION_PERIOD (default 10s in the internal cloud output).","triggerScenarios":"Running k6 cloud / --out cloud with K6_CLOUD_AGGREGATION_PERIOD=0s, or programmatically constructing the expv2 output with Config{AggregationPeriod: types.NullDurationFrom(0)}. Output.Start calls newCollector(config.AggregationPeriod.TimeDuration(), ...) at output.go:118 and wraps the failure as 'failed to initialize the samples collector'.","commonSituations":"Attempting to disable aggregation to get per-sample granularity in Cloud results; misconfigured CI env vars; overriding defaults in k6-operator deployments without validating values.","solutions":["Set K6_CLOUD_AGGREGATION_PERIOD to a positive whole-second value, e.g. 10s (default) or 1s for finer granularity","If the goal was per-sample data, understand the cloud output always aggregates in whole-second buckets; use the JSON output locally instead"],"exampleFix":"# before\nK6_CLOUD_AGGREGATION_PERIOD=0s k6 run -o cloud script.js\n\n# after\nK6_CLOUD_AGGREGATION_PERIOD=1s k6 run -o cloud script.js","handlingStrategy":"validation","validationCode":"# shell: guard the env var before invoking k6\nP=\"${K6_CLOUD_AGGREGATION_PERIOD:-10s}\"\n[ \"$(( $(date -d \"${P%s}\" +%s 2>/dev/null || echo 0) ))\" -ge 1 ] 2>/dev/null || { echo \"aggregation period must be >= 1s\"; exit 1; }\nK6_CLOUD_AGGREGATION_PERIOD=\"$P\" k6 run -o cloud script.js","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat 1s as the floor for K6_CLOUD_AGGREGATION_PERIOD; there is no 'no aggregation' mode for the cloud output","Prefer leaving the default (10s) unless Cloud dashboard granularity genuinely requires 1s"],"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"}