grafana/k6 · error

aggregation wait period is not allowed to have sub-second pr

Error message

aggregation wait period is not allowed to have sub-second precision

What it means

Returned by newCollector (output/cloud/expv2/collect.go:78-80) when the aggregation wait period has sub-second precision (waitPeriod != waitPeriod.Truncate(time.Second)). Like the aggregation period, the wait period participates in whole-second bucket arithmetic (collect.go:164 divides by the aggregation period after subtracting the wait), so fractional seconds such as 300ms are rejected.

Source

Thrown at output/cloud/expv2/collect.go:79

	// 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
}

// CollectSamples drain the buffer and collect all the samples.
func (c *collector) CollectSamples(containers []metrics.SampleContainer) {
	// Distribute all newly buffered samples into related buckets
	for _, sampleContainer := range containers {
		samples := sampleContainer.GetSamples()

		for i := range samples {
			c.collectSample(samples[i])

View on GitHub (pinned to 93accf6570)

Solutions

  1. Round the wait period to whole seconds; the minimum valid value is 1s

Example fix

# before
K6_CLOUD_AGGREGATION_WAIT_PERIOD=300ms k6 run -o cloud script.js

# after
K6_CLOUD_AGGREGATION_WAIT_PERIOD=1s k6 run -o cloud script.js
Defensive patterns

Strategy: validation

Validate before calling

# shell: require whole seconds for the wait period too
W="${K6_CLOUD_AGGREGATION_WAIT_PERIOD:-5s}"
case "$W" in *ms | *us | *ns | *.*) echo "wait period must be whole seconds"; exit 1;; esac
export K6_CLOUD_AGGREGATION_WAIT_PERIOD="$W"

Prevention

When it happens

Trigger: K6_CLOUD_AGGREGATION_WAIT_PERIOD=300ms or 1.5s, or programmatic config AggregationWaitPeriod: types.NullDurationFrom(300*time.Millisecond). Output.Start returns 'failed to initialize the samples collector: aggregation wait period is not allowed to have sub-second precision'.

Common situations: Fine-grained latency tuning of the Cloud output pipeline; values expressed in milliseconds by deployment tooling.

Related errors


AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15). Data as JSON: /api/errors/e32d478d0c916062. Report an issue: GitHub.