grafana/k6 · warning

execution is already paused

Error message

execution is already paused

What it means

Scheduler.SetPaused(true) backs the `k6 pause` command and the REST API status endpoint. If the test is paused and has not started yet (the pre-start paused state, !HasStarted && IsPaused), pausing again returns this error instead of being a no-op. The check exists because pre-start pause is handled by the state machine rather than by the executors themselves.

Source

Thrown at internal/execution/scheduler.go:579

// will cause k6 to initialize all needed VUs, but it won't actually start the
// test. Later, the test can be started for real by resuming/unpausing it from
// the REST API.
//
// After a test is actually started, it may become impossible to pause it again.
// That is signaled by having SetPaused(true) return an error. The likely cause
// is that some of the executors for the test don't support pausing after the
// test has been started.
//
// IMPORTANT: Currently only the externally controlled executor can be paused
// and resumed multiple times in the middle of the test execution! Even then,
// "pausing" is a bit misleading, since k6 won't pause in the middle of the
// currently executing iterations. It will allow the currently in-progress
// iterations to finish, and it just won't start any new ones nor will it
// increment the value returned by GetCurrentTestRunDuration().
func (e *Scheduler) SetPaused(pause bool) error {
	if !e.state.HasStarted() && e.state.IsPaused() {
		if pause {
			return fmt.Errorf("execution is already paused")
		}
		e.state.Test.Logger.Debug("Starting execution")
		return e.state.Resume()
	}

	for _, exec := range e.executors {
		pausableExecutor, ok := exec.(lib.PausableExecutor)
		if !ok {
			return fmt.Errorf(
				"%s executor '%s' doesn't support pause and resume operations after its start",
				exec.GetConfig().GetType(), exec.GetConfig().GetName(),
			)
		}
		if err := pausableExecutor.SetPaused(pause); err != nil {
			return err
		}
	}
	if pause {

View on GitHub (pinned to 93accf6570)

Solutions

  1. Query status first: GET /v1 status (or `k6 status`) and only pause when data.attributes.paused is false
  2. If you meant to start the run, send resume instead: `k6 resume` or PUT with paused=false
  3. Make control scripts idempotent: treat the message 'execution is already paused' as success, not failure

Example fix

# before: control loop pauses blindly
k6 pause
k6 pause   # second call while still pre-start -> execution is already paused

# after: check state, then act
k6 status  # inspect paused/started attributes
k6 pause   # only when not already paused
Defensive patterns

Strategy: validation

Validate before calling

# check the current status before sending pause
STATUS=$(curl -s http://localhost:6565/v1/status)
PAUSED=$(printf '%s' "$STATUS" | grep -o '"paused":[^,}]*' | cut -d: -f2)
if [ "$PAUSED" = "false" ]; then
  curl -s -X PUT http://localhost:6565/v1/status \
    -H 'Content-Type: application/json' \
    -d '{"data":{"type":"status","id":"1","attributes":{"paused":true}}}'
fi

Try / catch

# orchestrator: treat 'already paused' as the desired end state, not an error
if ! k6 pause 2>/tmp/pause.err; then
  grep -q 'execution is already paused' /tmp/pause.err || { cat /tmp/pause.err; exit 1; }
  echo 'target already paused - ok'
fi

Prevention

When it happens

Trigger: PUT /v1/status with data.attributes.paused=true (or running `k6 pause`) when the run is already in the paused-before-started state - typically a control script that fires pause twice, or a retry of a request that actually succeeded.

Common situations: Automation harnesses or dashboards driving the k6 REST API (port 6565) that race each other or double-fire pause calls; CI orchestration that pauses during initialization and then pauses again after a timeout.

Related errors


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