{"record":{"id":"368658b18d95ec37","repo":"grafana/k6","slug":"w-w","errorCode":null,"errorMessage":"%w: %w","messagePattern":"%w: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/context.go","lineNumber":101,"sourceCode":"\t\tcase <-ctx.Done():\n\t\t}\n\t}()\n\treturn ctx\n}\n\n// ContextErr returns ctx.Err() and, if present, appends the cancel cause.\nfunc ContextErr(ctx context.Context) error {\n\terr := ctx.Err()\n\tif err == nil {\n\t\treturn nil\n\t}\n\n\tcause := context.Cause(ctx)\n\tif cause == nil || errors.Is(err, cause) {\n\t\treturn err\n\t}\n\n\treturn fmt.Errorf(\"%w: %w\", err, cause)\n}\n","sourceCodeStart":83,"sourceCodeEnd":103,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/common/context.go#L83-L103","documentation":"ContextErr is k6-browser's standard cancellation reporter: it takes ctx.Err() (context.Canceled or context.DeadlineExceeded) and, when the context was cancelled with a cause (context.WithCancelCause), appends that cause as '<ctx error>: <cause>'. So this message is a carrier: the suffix (lost connection, websocket close code, timeout cause) identifies what actually aborted the operation.","triggerScenarios":"Any browser operation running on a context that gets cancelled: global timeout exceeded (K6_BROWSER_GLOBAL_TIMEOUT), iteration context cancelled at test end, or a connection-level cancelCtx cause such as 'connection closed with websocket code: 1006' or 'lost connection while closing the browser'.","commonSituations":"Users see this and fixate on 'context canceled' while the actionable detail is after the colon; typical sources are per-action timeouts too low (timeouts.default), test abort mid-navigation, or a browser crash whose real error was recorded as the cause.","solutions":["Read the part after the colon — it names the true cause; fix that (raise timeout, stabilize the browser, await operations).","For deadline-exceeded causes, increase the relevant timeout option (timeouts: { default: '30s' } or K6_BROWSER_TIMEOUT/default settings).","For cancellation at teardown, await pending awaits before the scenario ends.","For connection-loss causes, follow the guidance for errors [643]/[650]/[651]."],"exampleFix":"// k6 script: raise browser action timeout\n// before\nexport const options = { browser: { type: 'chromium' } };\n\n// after\nexport const options = {\n  browser: { type: 'chromium' },\n  // per-action default used for the cancelled operation\n  settings: undefined,\n};\n// simplest: raise via timeout option when the cause says deadline exceeded","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await page.goto(url);\n} catch (e) {\n  const s = String(e);\n  if (/context deadline exceeded/.test(s)) {\n    // real timeout: raise per-action timeout or waitUntil choice\n    await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60_000 });\n  } else if (/context canceled/.test(s)) {\n    // aborted elsewhere: the suffix after ': ' names the cause (connection lost, teardown, ...)\n    console.error('operation cancelled, cause:', s.split(': ').slice(1).join(': '));\n  } else {\n    throw e;\n  }\n}","preventionTips":["Always read the text after the colon — it is the root cause, not 'context canceled' itself.","Set explicit timeouts (script options or action args) so deadline causes point at the right knob.","Log full error strings during development; truncated messages hide the cause suffix."],"tags":["context","cancellation","timeout","browser","diagnostics"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}