grafana/k6 · error
aggregation period is not allowed to have sub-second precisi
Error message
aggregation period is not allowed to have sub-second precision
What it means
Returned by newCollector (output/cloud/expv2/collect.go:69-71) when the aggregation period is not a whole number of seconds (aggrPeriod != aggrPeriod.Truncate(time.Second)). Bucket boundaries are computed in whole seconds — bucketID is UnixNano/period and the flushed MetricSet reports aggregation_period in seconds as a uint32 (flush.go:183) — so sub-second precision (e.g. 500ms) cannot be represented faithfully and is rejected.
Source
Thrown at output/cloud/expv2/collect.go:70
nowFunc func() time.Time
aggregationPeriod time.Duration
waitPeriod time.Duration
// we should no longer have to handle metrics that have times long in the past. So instead of a
// map, we can probably use a simple slice (or even an array!) as a ring buffer to store the
// aggregation buckets. This should save us a some time, since it would make the lookups and WaitPeriod
// checks basically O(1). And even if for some reason there are occasional metrics with past times that
// don't fit in the chosen ring buffer size, we could just send them along to the buffer unaggregated
timeBuckets map[int64]map[metrics.TimeSeries]metricValue
}
func newCollector(aggrPeriod, waitPeriod time.Duration) (*collector, error) {
if aggrPeriod == 0 {
return nil, errors.New("aggregation period is not allowed to be zero")
}
if aggrPeriod != aggrPeriod.Truncate(time.Second) {
return nil, errors.New("aggregation period is not allowed to have sub-second precision")
}
if waitPeriod == 0 {
// TODO: we could simplify the expiring logic
// just having an internal static logic.
// Like skip only not closed buckets bucketEnd > now.
return nil, errors.New("aggregation wait period is not allowed to be zero")
}
if waitPeriod != waitPeriod.Truncate(time.Second) {
return nil, errors.New("aggregation wait period is not allowed to have sub-second precision")
}
return &collector{
bq: bucketQ{},
nowFunc: time.Now,
timeBuckets: make(map[int64]map[metrics.TimeSeries]metricValue),
aggregationPeriod: aggrPeriod,
waitPeriod: waitPeriod,
}, nil
}View on GitHub (pinned to 93accf6570)
Solutions
- Round the period to whole seconds; the minimum valid value is 1s
- For near-real-time dashboards use 1s and accept the Cloud ingestion cadence, rather than fractional seconds
Example fix
# before K6_CLOUD_AGGREGATION_PERIOD=500ms k6 run -o cloud script.js # after K6_CLOUD_AGGREGATION_PERIOD=1s k6 run -o cloud script.js
Defensive patterns
Strategy: validation
Validate before calling
# shell: require whole seconds
P="${K6_CLOUD_AGGREGATION_PERIOD:-10s}"
case "$P" in *ms | *us | *ns | *.*) echo "aggregation period must be whole seconds"; exit 1;; esac
export K6_CLOUD_AGGREGATION_PERIOD="$P" Prevention
- Both cloud aggregation knobs only accept whole-second multiples
- If a lower-latency pipeline is needed, use 1s rather than fractional values
When it happens
Trigger: K6_CLOUD_AGGREGATION_PERIOD=500ms (or 1500ms, 1.5s), or constructing the expv2 output config with AggregationPeriod: types.NullDurationFrom(500*time.Millisecond). Output.Start fails with 'failed to initialize the samples collector: aggregation period is not allowed to have sub-second precision'.
Common situations: Tuning aggregation latency down below 1s to make the Cloud dashboard update faster; values written as milliseconds by config tooling.
Related errors
- aggregation wait period is not allowed to have sub-second pr
- aggregation period is not allowed to be zero
- aggregation wait period is not allowed to be zero
- tests with unspecified duration are not allowed when outputt
- a /v1 suffix is expected in the Cloud service's BaseURL path
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/35c21e32936ba922.
Report an issue: GitHub.