{"record":{"id":"c377a312c1c28033","repo":"grafana/k6","slug":"test-run-completed-before-k6-could-start","errorCode":null,"errorMessage":"test run completed before k6 could start","messagePattern":"test run completed before k6 could start","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cloudapi/provisioning/api.go","lineNumber":167,"sourceCode":"\t\tswitch v6.Status(status) {\n\t\tcase v6.StatusInitializing:\n\t\t\treturn nil\n\n\t\tcase v6.StatusAborted:\n\t\t\tvar abortMsg string\n\t\t\tfor _, e := range progress.StatusHistory {\n\t\t\t\tif e.Status == v6.StatusAborted && e.Message != \"\" {\n\t\t\t\t\tabortMsg = e.Message\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif abortMsg != \"\" {\n\t\t\t\treturn fmt.Errorf(\"test run aborted before starting: %s\", abortMsg)\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"test run aborted before starting\")\n\n\t\tcase v6.StatusCompleted:\n\t\t\treturn fmt.Errorf(\"test run completed before k6 could start\")\n\n\t\tdefault:\n\t\t\t// created, queued, or any unrecognised state — keep polling.\n\t\t\tif status != lastStatus {\n\t\t\t\tc.logger.WithField(\"status\", progress.FormatStatus()).Debug(\"test status\")\n\t\t\t\tlastStatus = status\n\t\t\t}\n\t\t}\n\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn ctx.Err()\n\t\tcase <-time.After(pollInterval):\n\t\t\t// continue polling\n\t\t}\n\t}\n}\n","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/grafana/k6/blob/01ffac6f245854c1b8adc6a69857c76a15f90022/internal/cloudapi/provisioning/api.go#L149-L185","documentation":"Returned by Client.WaitForTestRunReady (internal/cloudapi/provisioning/api.go:167) when the polled test run reports status 'completed' before k6 ever saw 'initializing'. The state machine moved to a terminal finished state while the local k6 process was still waiting for its cue to start executing, so there is nothing left to drive: the backend considers the run done. This usually indicates a state race or configuration degenerate enough that the backend finished (or thought it finished) instantly.","triggerScenarios":"A test configuration the backend executes/finishes with zero local work (e.g. zero VUs or a zero/blank schedule slipping through); replaying a StartLocalExecution whose idempotency key collides with an already-completed run; backend state machine anomalies where 'completed' skips 'initializing'.","commonSituations":"Scripts with misconfigured executors producing empty schedules; retrying a start request after a network error where the first request actually succeeded and the run already finished; backend incidents flipping run states.","solutions":["Open the test run page for the ID being polled and check its timeline and results — if it genuinely ran, your local invocation lost the race to another one.","Audit the script's executor config: every scenario needs a non-zero duration/VUs so the run has actual work.","Make sure each invocation generates a fresh run (the client already mints a new idempotency key per StartLocalExecution call) — never reuse a previous request.","If the run shows no work at all in the UI yet reports completed, report it with the run ID to k6 Cloud support."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Before starting, assert the script actually schedules work.\nfunc hasRunnableWork(opts lib.Options) bool {\n\tfor _, s := range opts.Scenarios {\n\t\tif s == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif d := s.GetDuration(); d > 0 || s.GetVUs() > 0 {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}","typeGuard":null,"tryCatchPattern":"if err := c.WaitForTestRunReady(ctx, testRunID, poll); err != nil {\n\tif strings.Contains(err.Error(), \"completed before k6 could start\") {\n\t\t// inspect the run page: either a state race or a degenerate zero-work config\n\t\tlog.Warnf(\"run %d reported completed during wait; inspect its timeline\", testRunID)\n\t}\n\treturn err\n}","preventionTips":["Validate every scenario has non-zero duration/VUs before invoking cloud provisioning.","Never retry StartLocalExecution with a reused request; let the client mint a fresh idempotency key each time.","Investigate duplicate/parallel invocations of the same load test definition in CI."],"tags":["k6","cloud","provisioning","test-run","state-machine","race-condition"],"backgroundTag":"test-run-state-conflict","analyzedSha":"01ffac6f245854c1b8adc6a69857c76a15f90022","analyzedAt":"2026-08-18T03:05:52.393Z","contentChangedAt":"2026-08-18T03:05:52.393Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}