{"record":{"id":"5950f2afbaa92c40","repo":"grafana/k6","slug":"create-or-find-load-test-w","errorCode":null,"errorMessage":"create or find load test: %w","messagePattern":"create or find load test: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cloudapi/provisioning/provision.go","lineNumber":59,"sourceCode":"type ProvisionResult struct {\n\t// TestRunID is the ID of the provisioned test run.\n\tTestRunID int64\n\n\t// TestRunDetailsPageURL is the URL of the test run details page.\n\tTestRunDetailsPageURL string\n\n\t// RuntimeConfig carries the metrics, secrets, and token\n\t// configuration returned by the provisioning API.\n\tRuntimeConfig RuntimeConfig\n}\n\n// ProvisionLocalExecution orchestrates the full local-execution\n// provisioning flow: CreateOrFindLoadTest → StartLocalExecution →\n// optional UploadArchive → WaitForTestRunReady.\nfunc (c *Client) ProvisionLocalExecution(ctx context.Context, params ProvisionParams) (*ProvisionResult, error) {\n\tloadTestID, err := c.v6Client.CreateOrFindLoadTest(ctx, params.ProjectID, params.Name)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"create or find load test: %w\", err)\n\t}\n\n\t// Serialise archive once to get its byte-length for the\n\t// start_local_execution body. The same buffer is reused for\n\t// the S3 upload to avoid a second serialisation.\n\tvar (\n\t\tarchiveSize  int64\n\t\tarchiveBytes []byte\n\t)\n\tif params.Archive != nil {\n\t\tvar buf bytes.Buffer\n\t\tif err := params.Archive.Write(&buf); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"serialising archive: %w\", err)\n\t\t}\n\t\tarchiveSize = int64(buf.Len())\n\t\tarchiveBytes = buf.Bytes()\n\t}\n","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/grafana/k6/blob/01ffac6f245854c1b8adc6a69857c76a15f90022/internal/cloudapi/provisioning/provision.go#L41-L77","documentation":"First step of ProvisionLocalExecution failed: c.v6Client.CreateOrFindLoadTest(ctx, projectID, name) could not create or locate the cloud load test. This wraps any failure of the v6 cloud API call (auth, permissions, invalid project, network) under the 'create or find load test' prefix, so the underlying error identifies the real cause.","triggerScenarios":"Invalid or expired K6_CLOUD_TOKEN (401), projectID the token has no access to (403/404), empty or duplicate-resolving test name rejected by the API, network failure to the /cloud/v6 load-tests endpoint, or a corrupted options payload preventing test creation.","commonSituations":"Token rotated in Grafana Cloud but not refreshed locally (fix with k6 cloud login), --project-id pointing at a project in another org, CI using a masked/expired token, or a stack mismatch after changing K6_CLOUD_HOST.","solutions":["Run `k6 cloud login` to refresh token and stack, then retry","Verify projectID: pass --project-id explicitly or set K6_CLOUD_PROJECT_ID to a project your token can see","Read the wrapped error — a ResponseError with status/body tells you whether it is auth (401), permissions (403), or input (400)","Retry once for transient network/5xx failures before investigating further"],"exampleFix":"// before\nres, err := client.ProvisionLocalExecution(ctx, provisioning.ProvisionParams{ProjectID: 0, Name: name})\n\n// after\n// resolve and validate the project first\nprojectID, err := resolveProjectID(gs, &cloudConfig)\nif err != nil { return err }\nres, err := client.ProvisionLocalExecution(ctx, provisioning.ProvisionParams{ProjectID: projectID, Name: name})","handlingStrategy":"retry","validationCode":"if projectID <= 0 {\n    return fmt.Errorf(\"projectID must be a positive cloud project ID\")\n}\nif name == \"\" {\n    return fmt.Errorf(\"test name must not be empty\")\n}","typeGuard":null,"tryCatchPattern":"loadTestID, err := c.v6Client.CreateOrFindLoadTest(ctx, projectID, name)\nif err != nil {\n    var respErr *cloudapiv6.ResponseError\n    if errors.As(err, &respErr) && respErr.Response.StatusCode == 401 {\n        return 0, fmt.Errorf(\"token expired; re-run `k6 cloud login`: %w\", err)\n    }\n    if isTransient(err) { /* retry with backoff */ }\n    return 0, err\n}","preventionTips":["Validate token + project before provisioning (call ListProjects once at startup)","Refresh login config in CI jobs as a scheduled step so tokens never silently expire","Wrap project/name resolution with clear errors so the provisioning call gets valid inputs"],"tags":["cloud-api","provisioning","auth","project-id"],"backgroundTag":"api-request-failed","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"}