{"record":{"id":"930ef15e712f00e0","repo":"grafana/k6","slug":"execution-is-already-paused","errorCode":null,"errorMessage":"execution is already paused","messagePattern":"execution is already paused","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/execution/scheduler.go","lineNumber":579,"sourceCode":"// will cause k6 to initialize all needed VUs, but it won't actually start the\n// test. Later, the test can be started for real by resuming/unpausing it from\n// the REST API.\n//\n// After a test is actually started, it may become impossible to pause it again.\n// That is signaled by having SetPaused(true) return an error. The likely cause\n// is that some of the executors for the test don't support pausing after the\n// test has been started.\n//\n// IMPORTANT: Currently only the externally controlled executor can be paused\n// and resumed multiple times in the middle of the test execution! Even then,\n// \"pausing\" is a bit misleading, since k6 won't pause in the middle of the\n// currently executing iterations. It will allow the currently in-progress\n// iterations to finish, and it just won't start any new ones nor will it\n// increment the value returned by GetCurrentTestRunDuration().\nfunc (e *Scheduler) SetPaused(pause bool) error {\n\tif !e.state.HasStarted() && e.state.IsPaused() {\n\t\tif pause {\n\t\t\treturn fmt.Errorf(\"execution is already paused\")\n\t\t}\n\t\te.state.Test.Logger.Debug(\"Starting execution\")\n\t\treturn e.state.Resume()\n\t}\n\n\tfor _, exec := range e.executors {\n\t\tpausableExecutor, ok := exec.(lib.PausableExecutor)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\n\t\t\t\t\"%s executor '%s' doesn't support pause and resume operations after its start\",\n\t\t\t\texec.GetConfig().GetType(), exec.GetConfig().GetName(),\n\t\t\t)\n\t\t}\n\t\tif err := pausableExecutor.SetPaused(pause); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tif pause {","sourceCodeStart":561,"sourceCodeEnd":597,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/execution/scheduler.go#L561-L597","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Query status first: GET /v1 status (or `k6 status`) and only pause when data.attributes.paused is false","If you meant to start the run, send resume instead: `k6 resume` or PUT with paused=false","Make control scripts idempotent: treat the message 'execution is already paused' as success, not failure"],"exampleFix":"# before: control loop pauses blindly\nk6 pause\nk6 pause   # second call while still pre-start -> execution is already paused\n\n# after: check state, then act\nk6 status  # inspect paused/started attributes\nk6 pause   # only when not already paused","handlingStrategy":"validation","validationCode":"# check the current status before sending pause\nSTATUS=$(curl -s http://localhost:6565/v1/status)\nPAUSED=$(printf '%s' \"$STATUS\" | grep -o '\"paused\":[^,}]*' | cut -d: -f2)\nif [ \"$PAUSED\" = \"false\" ]; then\n  curl -s -X PUT http://localhost:6565/v1/status \\\n    -H 'Content-Type: application/json' \\\n    -d '{\"data\":{\"type\":\"status\",\"id\":\"1\",\"attributes\":{\"paused\":true}}}'\nfi","typeGuard":null,"tryCatchPattern":"# orchestrator: treat 'already paused' as the desired end state, not an error\nif ! k6 pause 2>/tmp/pause.err; then\n  grep -q 'execution is already paused' /tmp/pause.err || { cat /tmp/pause.err; exit 1; }\n  echo 'target already paused - ok'\nfi","preventionTips":["Make every control-API call read-modify-write: GET /v1 status, then decide","Serialize control commands through one orchestrator instead of concurrent dashboards/jobs","Log the full status response on failure so double-pauses are obvious in hindsight"],"tags":["pause-resume","rest-api","state-machine","orchestration"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}