{"record":{"id":"14850ced5d179e86","repo":"grafana/k6","slug":"failed-to-authenticate-with-k6-cloud","errorCode":null,"errorMessage":"failed to authenticate with k6 Cloud","messagePattern":"failed to authenticate with k6 Cloud","errorType":"http","errorClass":"ErrNotAuthenticated","httpStatus":401,"severity":"error","filePath":"internal/cloudapi/httperr/httperr.go","lineNumber":15,"sourceCode":"// Package httperr contains HTTP-status-code error helpers shared by k6\n// Cloud's API clients (cloudapi, internal/cloudapi/v6). It only covers the\n// part of their CheckResponse-style functions that's genuinely identical\n// across them - classifying 401/403 - everything else about decoding an\n// error response body differs between API versions.\npackage httperr\n\nimport (\n\t\"errors\"\n\t\"net/http\"\n)\n\nvar (\n\t// ErrNotAuthenticated maps HTTP 401.\n\tErrNotAuthenticated = errors.New(\"failed to authenticate with k6 Cloud\")\n\t// ErrNotAuthorized maps HTTP 403.\n\tErrNotAuthorized = errors.New(\"not allowed to upload result to k6 Cloud\")\n)\n\n// ClassifyStatus returns ErrNotAuthenticated for HTTP 401, ErrNotAuthorized\n// for HTTP 403, and nil for any other status code.\nfunc ClassifyStatus(statusCode int) error {\n\tswitch statusCode {\n\tcase http.StatusUnauthorized:\n\t\treturn ErrNotAuthenticated\n\tcase http.StatusForbidden:\n\t\treturn ErrNotAuthorized\n\tdefault:\n\t\treturn nil\n\t}\n}\n","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/grafana/k6/blob/01ffac6f245854c1b8adc6a69857c76a15f90022/internal/cloudapi/httperr/httperr.go#L1-L32","documentation":"After the isEnabled action succeeds (frame.go:1475), k6 asserts the result is a bool and errors with 'checking is %q enabled: unexpected type %T' otherwise. The state check returns a Go bool, so a non-bool (typically nil) indicates the action pipeline yielded an unexpected value: a race where the frame or execution context went away between resolution and result, or a browser-module bug. It is a defensive invariant error, not an application-level disabled state.","triggerScenarios":"Navigation or iframe swap between selector resolution and result; nil result on a rare action error path; CDP session teardown races during the check; k6 browser-module regression in value conversion.","commonSituations":"CI flakiness around page transitions; SPA tests where checks coincide with rerenders; occurrences right after upgrading k6.","solutions":["Retry once after stabilizing the page (waitForLoadState/locator.waitFor) since the usual cause is a transient race.","Avoid running state checks while navigation is in flight.","Capture K6_DEBUG=true logs to identify the racing navigation.","Report reproducible cases to grafana/k6 with script and versions."],"exampleFix":"// before\nconst ok = await page.isEnabled('#submit');\n\n// after\nawait page.waitForLoadState('domcontentloaded');\nlet ok;\ntry { ok = await page.isEnabled('#submit'); }\ncatch (e) {\n  if (!String(e).includes('unexpected type')) throw e;\n  ok = await page.isEnabled('#submit'); // single retry\n}","handlingStrategy":"retry","validationCode":"await page.waitForLoadState('domcontentloaded');","typeGuard":null,"tryCatchPattern":"try {\n  return await page.isEnabled(sel);\n} catch (e) {\n  if (!String(e).includes('unexpected type')) throw e;\n  await page.waitForLoadState('domcontentloaded');\n  return await page.isEnabled(sel); // retry once past the race\n}","preventionTips":["Sequence state checks after load-state waits, not during transitions.","Avoid racing checks with form submissions that navigate.","Report persistent occurrences upstream with a repro."],"tags":["k6","browser","isenabled","type-assertion","race"],"backgroundTag":"unexpected-eval-return-type","analyzedSha":"01ffac6f245854c1b8adc6a69857c76a15f90022","analyzedAt":"2026-08-18T03:05:52.393Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}