grafana/k6 · error
max_vus
Error message
max_vus: %w
What it means
Returned by Client.StartLocalExecution (internal/cloudapi/provisioning/api.go:206) when req.MaxVUs (int64) does not fit in int32, because the underlying cloud SDK models max_vus as int32 (toInt32 at api.go:296-301 rejects anything outside [-2147483648, 2147483647]). A VU count above 2,147,483,647 is far beyond any executable load, so in practice this signals garbage input (overflow/negative sentinel) rather than an ambitious test.
Solutions
- Check how the caller computes MaxVUs (usually lib.Options.Scenarios VU totals in cmd) and clamp or fail earlier on unreasonable values.
- Replace int sentinel values like -1 with a real count before constructing the request.
- Validate 0 < MaxVUs <= 2_000_000 (k6 Cloud's practical ceiling) before calling StartLocalExecution.
Example fix
// before
resp, err := c.StartLocalExecution(ctx, id, provisioning.StartLocalExecutionRequest{MaxVUs: computedMaxVUs})
// after
if req.MaxVUs <= 0 || req.MaxVUs > 2_000_000 {
return fmt.Errorf("max_vus %d out of supported range (1..2000000)", req.MaxVUs)
}
resp, err := c.StartLocalExecution(ctx, id, provisioning.StartLocalExecutionRequest{MaxVUs: computedMaxVUs}) Defensive patterns
Strategy: validation
Validate before calling
const maxCloudVUs = int64(2_000_000) // practical k6 Cloud ceiling, far under int32
func validMaxVUs(v int64) bool {
return v > 0 && v <= maxCloudVUs
}
if !validMaxVUs(req.MaxVUs) {
return fmt.Errorf("max_vus %d outside supported range 1..%d", req.MaxVUs, maxCloudVUs)
} Try / catch
if _, err := c.StartLocalExecution(ctx, id, req); err != nil {
if strings.Contains(err.Error(), "max_vus") && strings.Contains(err.Error(), "overflows int32") {
// input bug, not transient: fix how MaxVUs is computed (sentinels/units)
return fmt.Errorf("computed max_vus=%d is invalid; check scenario VU totals", req.MaxVUs)
}
} Prevention
- Compute MaxVUs from scenario definitions, never from untrusted arithmetic.
- Outlaw -1/0 sentinels in request structs — use pointers or explicit optional fields.
- Range-check all numeric request fields at the construction boundary.
When it happens
Trigger: StartLocalExecutionRequest.MaxVUs > math.MaxInt32 (or < math.MinInt32): usually an uninitialized/negative value used as a sentinel, or a computed sum over overflowing from a misconfigured options structure.
Common situations: Callers deriving MaxVUs via arithmetic on untrusted config; using -1 as 'unknown' marker and forgetting to replace it; tests with absurd fixture numbers.
Related errors
AI-assisted analysis of grafana/k6@01ffac6f24 (2026-08-18).
Data as JSON: /api/errors/0919c4057fe57a3c.
Report an issue: GitHub.
Appendix: source
Thrown at internal/cloudapi/provisioning/api.go:206
// safe retries. The caller provides options as pre-marshalled JSON.
func (c *Client) StartLocalExecution(
ctx context.Context, loadTestID int64, req StartLocalExecutionRequest,
) (*StartLocalExecutionResponse, error) {
// Generate idempotency key: 8 random bytes hex-encoded (16 chars).
var key [8]byte
if _, err := rand.Read(key[:]); err != nil {
return nil, fmt.Errorf("generating idempotency key: %w", err)
}
// SDK adapter: unmarshal json.RawMessage → map[string]any.
var opts map[string]any
if err := json.Unmarshal(req.Options, &opts); err != nil {
return nil, fmt.Errorf("unmarshalling options for SDK: %w", err)
}
maxVUs, err := toInt32(req.MaxVUs)
if err != nil {
return nil, fmt.Errorf("max_vus: %w", err)
}
totalDuration, err := toInt32(req.TotalDuration)
if err != nil {
return nil, fmt.Errorf("total_duration: %w", err)
}
sdkReq := k6cloud.NewStartLocalExecutionTestRequest(opts, maxVUs, totalDuration)
if req.ArchiveSize > 0 {
v, err := toInt32(req.ArchiveSize)
if err != nil {
return nil, fmt.Errorf("archive_size: %w", err)
}
sdkReq.SetArchiveSize(v)
} else {
sdkReq.SetArchiveSizeNil()
}
View on GitHub (pinned to 01ffac6f24)