{"record":{"id":"036b52e513d0dbb7","repo":"grafana/k6","slug":"notify-test-run-completed-w","errorCode":null,"errorMessage":"notify test run completed: %w","messagePattern":"notify test run completed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cloudapi/provisioning/notify.go","lineNumber":77,"sourceCode":"\t// Authorization: Bearer <token>.\n\tscopedCtx := context.WithValue(ctx, k6cloud.ContextAccessToken, testRunToken)\n\n\tmodel := k6cloud.NewScriptExecutionCompletedNotificationApiModel(\"script_execution_completed\")\n\tif ne := mapTestErrorToNotifyCode(testErr); ne != nil {\n\t\tmodel.SetError(*k6cloud.NewScriptExecutionError(ne.Code, ne.Reason))\n\t} else {\n\t\tmodel.SetErrorNil()\n\t}\n\n\thr, err := c.apiClient.ProvisioningAPI.\n\t\tTestRunsNotify(scopedCtx, testRunID).\n\t\tScriptExecutionCompletedNotificationApiModel(model).\n\t\tExecute()\n\tdefer closeResponse(hr, &err)\n\n\tif hr != nil {\n\t\tif respErr := CheckResponse(hr); respErr != nil {\n\t\t\treturn fmt.Errorf(\"notify test run completed: %w\", respErr)\n\t\t}\n\t}\n\tif err != nil {\n\t\treturn fmt.Errorf(\"notify test run completed: %w\", err)\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":59,"sourceCodeEnd":86,"githubUrl":"https://github.com/grafana/k6/blob/8d06114777191d21ef885d05c5f8aa9e1ed838ae/internal/cloudapi/provisioning/notify.go#L59-L86","documentation":"Raised by provisioning.Client.NotifyTestRunCompleted after POST /provisioning/v1/test_runs/{id}/notify returned a non-2xx HTTP status. The provisioning package's CheckResponse(hr) inspects the response, so this error means the cloud API received the request but rejected it — the wrapped value is usually a ResponseError carrying status code and body. The notify call uses the scoped test-run token (injected via context), not the long-lived API token, so auth failures here implicate that scoped token, not your login token.","triggerScenarios":"Calling NotifyTestRunCompleted with an expired or wrong testRunToken (401/403), a testRunID that was never provisioned or already closed (404), a malformed notification model (400), or a 4xx from the provisioning API. 5xx is retried by the SDK, so surfacing here means retries were exhausted or the status was 4xx.","commonSituations":"Local-execution flow where the run took longer than the token/URL validity, re-using a testRunID from a previous run after the cloud run was deleted, clock skew, or a proxy stripping the Authorization header.","solutions":["Verify testRunID and testRunToken come from the same StartLocalExecution response and were not reused from an earlier run","Inspect the wrapped ResponseError body for the exact API reason (status code + message) before changing anything","If 401/403, re-provision to obtain a fresh scoped token; do not substitute the global K6_CLOUD_TOKEN","If 5xx persisted through SDK retries, retry NotifyTestRunCompleted after a short delay once the service recovers"],"exampleFix":"// before\n_ = client.NotifyTestRunCompleted(ctx, staleRunID, staleToken, testErr)\n\n// after\nif err := client.NotifyTestRunCompleted(ctx, result.TestRunID, result.RuntimeConfig.Token, testErr); err != nil {\n    var respErr *cloudapi.ResponseError\n    if errors.As(err, &respErr) {\n        logger.Errorf(\"notify rejected: status=%d body=%s\", respErr.Response.StatusCode, respErr.Error())\n    }\n    return err\n}","handlingStrategy":"retry","validationCode":"// ensure the run + token pair is fresh before notifying\nif result == nil || result.TestRunID == 0 {\n    return fmt.Errorf(\"cannot notify: no provisioned test run\")\n}","typeGuard":"func isHTTPResponseError(err error) bool {\n    var re *cloudapiv6.ResponseError\n    return errors.As(err, &re)\n}","tryCatchPattern":"if err := client.NotifyTestRunCompleted(ctx, runID, token, testErr); err != nil {\n    var respErr *cloudapiv6.ResponseError\n    if errors.As(err, &respErr) && respErr.Response != nil && respErr.Response.StatusCode >= 500 {\n        time.Sleep(5 * time.Second) // SDK already retried 5xx; back off further\n        err = client.NotifyTestRunCompleted(ctx, runID, token, testErr)\n    }\n    if err != nil { logger.WithError(err).Warn(\"cloud notify failed; run may show as unfinished\") }\n}","preventionTips":["Propagate the scoped test-run token from ProvisionResult.RuntimeConfig instead of re-using the global API token","Notify promptly after the run finishes so the scoped token and run window are still valid","Log the response body on failure — it contains the cloud-side reason"],"tags":["cloud-api","http-response","provisioning","notify","auth"],"backgroundTag":"http-error-response","analyzedSha":"8d06114777191d21ef885d05c5f8aa9e1ed838ae","analyzedAt":"2026-08-18T03:05:52.393Z","contentChangedAt":"2026-08-18T03:05:52.393Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}