{"record":{"id":"d476d0f5ece26eb1","repo":"grafana/k6","slug":"dispatching-element-event-q-w","errorCode":null,"errorMessage":"dispatching element event %q: %w","messagePattern":"dispatching element event %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/element_handle.go","lineNumber":898,"sourceCode":"\t\treturn fmt.Errorf(\"double clicking on element: %w\", err)\n\t}\n\n\tapplySlowMo(h.ctx)\n\n\treturn nil\n}\n\n// DispatchEvent dispatches a DOM event to the element.\nfunc (h *ElementHandle) DispatchEvent(typ string, eventInit any) error {\n\tdispatchEvent := func(apiCtx context.Context, handle *ElementHandle) (any, error) {\n\t\treturn handle.dispatchEvent(apiCtx, typ, eventInit)\n\t}\n\topts := NewElementHandleBaseOptions(h.DefaultTimeout())\n\tdispatchEventAction := h.newAction(\n\t\t[]string{}, dispatchEvent, opts.Force, withRetry, opts.NoWaitAfter, opts.Timeout,\n\t)\n\tif _, err := call(h.ctx, dispatchEventAction, opts.Timeout); err != nil {\n\t\treturn fmt.Errorf(\"dispatching element event %q: %w\", typ, err)\n\t}\n\n\tapplySlowMo(h.ctx)\n\n\treturn nil\n}\n\n// Fill types the given value into the element.\nfunc (h *ElementHandle) Fill(value string, opts *ElementHandleBaseOptions) error {\n\tfill := func(apiCtx context.Context, handle *ElementHandle) (any, error) {\n\t\treturn nil, handle.fill(apiCtx, value)\n\t}\n\tfillAction := h.newAction(\n\t\t[]string{\"visible\", \"enabled\", \"editable\"},\n\t\tfill, opts.Force, withRetry, opts.NoWaitAfter, opts.Timeout,\n\t)\n\tif _, err := call(h.ctx, fillAction, opts.Timeout); err != nil {\n\t\treturn fmt.Errorf(\"filling element: %w\", err)","sourceCodeStart":880,"sourceCodeEnd":916,"githubUrl":"https://github.com/grafana/k6/blob/3fcf5388d78cb382f0c0d42ec556a06bfd1b8dee/internal/js/modules/k6/browser/common/element_handle.go#L880-L916","documentation":"ElementHandle.dispatchEvent() wraps the failure of an action that evaluates an injected script (injected.dispatchEvent(node, type, eventInit)) in the element's execution context via Runtime.callFunctionOn. No actionability preconditions are checked, so failures come from the evaluation itself, the default timeout (30s), or a dead execution context.","triggerScenarios":"The element handle is detached (navigation or SPA re-render) so callFunctionOn fails with 'Could not find object with given id'; the page navigates while the script runs, destroying the execution context; the default timeout expires; eventInit contains non-serializable values (functions, DOM nodes, cyclic objects).","commonSituations":"Dispatching custom events in SPAs right after route changes; passing complex eventInit payloads built from page objects; handles cached from an earlier page state reused after navigation.","solutions":["Re-acquire the element handle immediately before dispatching, after any navigation","Keep eventInit a plain JSON-serializable object ({ bubbles: true, detail: {...} })","Increase the default timeout via the timeout option or K6_BROWSER_TIMEOUT env var","Wait for the page to settle: page.waitForLoadState('networkidle') before dispatching"],"exampleFix":"// before\nconst el = await page.$('input#q');\nawait page.goto('https://app.example.com/search');\nawait el.dispatchEvent('input', { bubbles: true }); // stale handle\n\n// after\nawait page.goto('https://app.example.com/search');\nconst el = await page.$('input#q');\nawait el.dispatchEvent('input', { bubbles: true, detail: { value: 'k6' } });","handlingStrategy":"try-catch","validationCode":"// Confirm the handle is still live before dispatching\nconst alive = await el.evaluate((e) => e.isConnected).catch(() => false);\nif (!alive) {\n  throw new Error('element detached; re-query before dispatchEvent');\n}\nawait el.dispatchEvent('input', { bubbles: true });","typeGuard":null,"tryCatchPattern":"try {\n  await el.dispatchEvent('input', { bubbles: true, detail: { v: 1 } });\n} catch (e) {\n  if (/Execution context|Could not find object|timed out/i.test(String(e.message))) {\n    await page.waitForLoadState();\n    const fresh = await page.$(sel);\n    await fresh.dispatchEvent('input', { bubbles: true, detail: { v: 1 } });\n  } else throw e;\n}","preventionTips":["Keep eventInit a plain JSON object (no functions, DOM nodes, or cycles)","Re-acquire the handle right after any navigation or route change","Dispatch state events only after the page has finished loading its listeners"],"tags":["browser","dispatch-event","dom-events","execution-context","stale-element","k6"],"backgroundTag":"execution-context-destroyed","analyzedSha":"3fcf5388d78cb382f0c0d42ec556a06bfd1b8dee","analyzedAt":"2026-08-18T03:05:52.393Z","contentChangedAt":"2026-08-18T03:05:52.393Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}