Heuristic:Webdriverio Webdriverio Stale Element Auto Refetch
| Knowledge Sources | |
|---|---|
| Domains | Browser_Automation, Debugging |
| Last Updated | 2026-02-12 01:00 GMT |
Overview
WebdriverIO automatically refetches elements when a "stale element reference" error is detected, handling DOM re-renders transparently without user intervention.
Description
When the DOM changes (e.g., after navigation, AJAX updates, or framework re-renders), previously found element references become stale. WebdriverIO's element command middleware detects stale element errors across all browser engines and automatically re-queries the element using its original selector, then retries the failed command. This is implemented in the `commandWrapper` middleware and handles browser-specific error message variations from Chrome, Firefox, Safari, and WebDriver BiDi.
Usage
This heuristic is automatically applied by WebdriverIO's middleware layer. Be aware of it when:
- Debugging flaky tests: If an element command succeeds after a DOM update, the auto-refetch likely fired silently.
- Performance-sensitive tests: Each refetch adds a `findElement` call. If you have many stale element errors, consider restructuring selectors or using `waitUntil`.
- Dynamic SPAs: Particularly useful with React, Vue, Angular apps where the DOM frequently re-renders.
The Insight (Rule of Thumb)
- Action: When any element command throws a stale element error, WebdriverIO re-finds the element using its original selector and retries the command.
- Value: Transparent error recovery — no user code changes needed.
- Trade-off: Adds one extra `findElement` network call per stale element occurrence. The refetched element may not be the same element if multiple elements match the selector.
- Compatibility: Works across all browsers (Chrome, Firefox, Safari, WebDriver BiDi).
Reasoning
Stale element references are one of the most common sources of test flakiness in browser automation. Different browsers report this error differently:
- Chrome: `"stale element reference: element is not attached to the page document"`
- Firefox: `"Element does not exist in cache"`
- Safari: `"A node reference could not be resolved: Stale element found when trying to create the node handle"`
- BiDi: `"no such element"`
WebdriverIO normalizes all these into a single recovery path.
Evidence from code:
From `packages/webdriverio/src/middlewares.ts:57-62`:
if (err.name === 'stale element reference' || isStaleElementError(err)) {
const element = await refetchElement(this, commandName)
this.elementId = element.elementId
this.parent = element.parent
return await fn(commandName, commandFn).apply(this, args)
}
Browser-specific stale element detection patterns:
// Chrome
'stale element reference: element is not attached to the page document'
// Firefox
'Element does not exist in cache'
// Safari
'A node reference could not be resolved: Stale element found'
// BiDi
'no such element'