grafana/k6 · error

total_duration: %w

Error message

total_duration: %w

What it means

Client.StartLocalExecution (internal/cloudapi/provisioning/api.go:210) converts req.TotalDuration (seconds, int64) to int32 for the cloud API schema. int32 max is ~2.1 billion seconds (~68 years), so a real duration never overflows; hitting this error means the value is wrong — typically a unit confusion (milliseconds or nanoseconds passed as seconds) or a garbage/negative sentinel.

Source

Thrown at internal/cloudapi/provisioning/api.go:210

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

	res, hr, err := c.apiClient.ProvisioningAPI.
		StartLocalExecutionTest(c.authCtx(ctx), loadTestID).
		K6IdempotencyKey(hex.EncodeToString(key[:])).
		StartLocalExecutionTestRequest(sdkReq).

View on GitHub (pinned to 93accf6570)

Solutions

  1. Verify the duration is expressed in seconds before building the request
  2. Range-check the computed total against a sane maximum (e.g. 30 days) and fail early with a clear message
  3. Re-run k6 inspect on the script to see the effective duration options
  4. Fix the upstream duration calculation rather than catching the error

Example fix

// before
req := provisioning.StartLocalExecutionRequest{
	TotalDuration: totalDurationMs, // oops: milliseconds, not seconds
}

// after
totalSeconds := int64(totalDuration / time.Second)
if totalSeconds <= 0 || totalSeconds > 30*24*3600 {
	return fmt.Errorf("implausible total duration: %ds", totalSeconds)
}
req := provisioning.StartLocalExecutionRequest{TotalDuration: totalSeconds}
Defensive patterns

Strategy: validation

Validate before calling

totalSeconds := int64(total / time.Second)
if totalSeconds <= 0 || totalSeconds > 365*24*3600 {
	return fmt.Errorf("total_duration %ds implausible; check units", totalSeconds)
}

Type guard

func fitsInt32(v int64) bool { return v >= math.MinInt32 && v <= math.MaxInt32 }

Try / catch

if err := client.StartLocalExecution(ctx, id, req); err != nil {
	if strings.HasPrefix(err.Error(), "total_duration:") {
		// suspect a unit mismatch (ms/ns passed as seconds) upstream
	}
	return err
}

Prevention

When it happens

Trigger: TotalDuration computed by summing executor durations with the wrong unit, a duration value derived from an unchecked env/flag, or an overflowed negative number from caller arithmetic.

Common situations: Custom tooling that translates durations and drops a division by time.Second; options with enormous -d values from templating mistakes.

Related errors


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