{"record":{"id":"3293233b670ad5dd","repo":"grafana/k6","slug":"99","errorCode":"99","errorMessage":"Thresholds have been crossed","messagePattern":"Thresholds have been crossed","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cmd/cloud.go","lineNumber":389,"sourceCode":"\t\t\tglobalCancel()\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// Stop progress rendering before printing final status to avoid ghost bars.\n\tprogressCancel()\n\tprogressBarWG.Wait()\n\n\tif testProgress == nil {\n\t\t//nolint:staticcheck\n\t\treturn errext.WithExitCodeIfNone(errors.New(\"Test progress error\"), exitcodes.CloudFailedToGetProgress)\n\t}\n\n\tc.printTestStatus(testProgress.FormatStatus())\n\n\tif testProgress.ThresholdsFailed() {\n\t\t//nolint:staticcheck\n\t\treturn errext.WithExitCodeIfNone(errors.New(\"Thresholds have been crossed\"), exitcodes.ThresholdsHaveFailed)\n\t}\n\tif testProgress.TestFailed() {\n\t\t//nolint:staticcheck\n\t\treturn errext.WithExitCodeIfNone(errors.New(\"The test has failed\"), exitcodes.CloudTestRunFailed)\n\t}\n\n\treturn nil\n}\n\nfunc (c *cmdCloud) printTestStatus(status string) {\n\tif !c.gs.Flags.Quiet {\n\t\tvalueColor := getColor(c.gs.Flags.NoColor || !c.gs.Stdout.IsTTY, color.FgCyan)\n\t\tprintToStdout(c.gs, fmt.Sprintf(\n\t\t\t\"     test status: %s\\n\", valueColor.Sprint(status),\n\t\t))\n\t} else {\n\t\tc.gs.Logger.WithField(\"run_status\", status).Debug(\"Test finished\")\n\t}","sourceCodeStart":371,"sourceCodeEnd":407,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/cmd/cloud.go#L371-L407","documentation":"After a `k6 cloud run` finishes, k6 inspects the final TestProgress: if testProgress.ThresholdsFailed() is true, this error is returned with exit code 99 (ThresholdsHaveFailed). It is not a malfunction — it is k6's designed contract of converting a failed threshold into a non-zero exit so CI gates can act on it.","triggerScenarios":"The cloud test run completes and the service reports at least one crossed threshold (e.g. http_req_duration p(95) above the configured limit). The final status line ('test status: ...') is printed before the error, naming the failing condition.","commonSituations":"Target system slower than the thresholds assume; thresholds copied from another environment; scaled-up load in cloud runs crossing limits that local runs passed; intentionally strict thresholds used as CI quality gates.","solutions":["Open the test run in Grafana Cloud and check the Thresholds tab to see which threshold crossed and by how much","Tune thresholds to values that reflect an acceptable SLO for the current environment","Fix the performance issue in the target system or reduce load if the thresholds are correct","In CI, treat exit code 99 as the deliberate quality-gate signal rather than retrying blindly"],"exampleFix":"// before: threshold set below real p(95)\nexport const options = {\n  thresholds: { http_req_duration: ['p(95)<200'] },\n};\n\n// after: align the threshold with the measured SLO\nexport const options = {\n  thresholds: { http_req_duration: ['p(95)<500'] },\n};","handlingStrategy":"validation","validationCode":"// script-side: keep thresholds in a shared module so local and cloud runs\n// assert the same SLOs before anything is uploaded\nimport { thresholds } from './slo.js';\nexport const options = { thresholds };","typeGuard":null,"tryCatchPattern":"err := runK6(\"cloud\", \"run\", \"script.js\")\nif exitCode(err) == 99 { // exitcodes.ThresholdsHaveFailed\n    // deliberate quality gate: collect the failing thresholds from the run URL\n    // and fail the pipeline step with that context\n}","preventionTips":["Baseline the target system first, then set thresholds with headroom above measured p(95)/p(99)","Treat exit code 99 as the designed CI gate signal, not a flaky failure to retry","Read the printed 'test status:' line and the run's Thresholds tab to see exactly which threshold crossed"],"tags":["cloud","thresholds","exit-code","test-result"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}