grafana/k6 · error

%s executor '%s' doesn't support pause and resume operations

Error message

%s executor '%s' doesn't support pause and resume operations after its start

What it means

Once a test has started, Scheduler.SetPaused asks each executor to pause via the lib.PausableExecutor interface - and only the externally-controlled executor implements it. If any scenario uses another executor type (constant-vus, ramping-vus, per-vu-iterations, shared-iterations, constant-arrival-rate, ramping-arrival-rate), the loop returns this error naming the executor type and scenario that cannot be paused. Pause/resume after start is an externally-controlled-only feature (used by the cloud/distributed control plane).

Source

Thrown at internal/execution/scheduler.go:588

// 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 {
		return e.state.Pause()
	}
	return e.state.Resume()
}

View on GitHub (pinned to 93accf6570)

Solutions

  1. If mid-test pause/resume is a hard requirement, drive the run with an externally-controlled executor scenario
  2. Otherwise remove pause/resume from your tooling - plan the whole load shape declaratively via scenarios (stages, startTime) instead
  3. Note the error names the first non-pausable executor; fixing that scenario alone is not enough, every scenario must be externally-controlled

Example fix

// before: normal scenario + external pause attempt -> error
export const options = { vus: 5, duration: '10m' };
// `k6 pause` fails: constant-vus executor 'default' doesn't support pause and resume

// after: externally-controlled executor can be paused/resumed after start
export const options = {
  scenarios: {
    ext: { executor: 'externally-controlled', vus: 2, maxVUs: 10, duration: '10m' },
  },
};
Defensive patterns

Strategy: validation

Validate before calling

// before wiring pause/resume buttons, verify every scenario is externally-controlled
import Options from './options.json';
const allPausable = Object.values(Options.scenarios ?? {}).every(
  (s) => s.executor === 'externally-controlled'
);
if (!allPausable) {
  throw new Error('pause/resume controls require externally-controlled scenarios only');
}

Prevention

When it happens

Trigger: `k6 pause` / `k6 resume` or PUT /v1/status {"data":{"attributes":{"paused":true}}} on a running test whose options.scenarios contain any executor other than 'externally-controlled'.

Common situations: Teams wiring generic pause/resume buttons into locally-run or self-hosted k6 via the REST API; porting cloud-driven test control flows to plain local scenarios.

Related errors


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