SeleniumHQ/selenium · error · TypeError
Custom locator did not return a WebElement
Error message
Custom locator did not return a WebElement
What it means
Thrown as a TypeError by WebDriver.findElementInternal_() when a custom locator function resolves to a value that is neither an array nor a WebElement instance. After calling locatorFn(context), the code checks `if (!(result instanceof WebElement))` and throws TypeError with the message 'Custom locator did not return a WebElement'. This is a contract violation: custom locators must return a WebElement or an array of WebElements.
Source
Thrown at javascript/selenium-webdriver/lib/webdriver.js:1054
}
/**
* @param {!Function} locatorFn The locator function to use.
* @param {!(WebDriver|WebElement)} context The search context.
* @return {!Promise<!WebElement>} A promise that will resolve to a list of
* WebElements.
* @private
*/
async findElementInternal_(locatorFn, context) {
let result = await locatorFn(context)
if (Array.isArray(result)) {
if (result.length === 0) {
throw new NoSuchElementError('Cannot locate an element with provided parameters')
}
result = result[0]
}
if (!(result instanceof WebElement)) {
throw new TypeError('Custom locator did not return a WebElement')
}
return result
}
/** @override */
async findElements(locator) {
let cmd = null
if (locator instanceof RelativeBy) {
cmd = new command.Command(command.Name.FIND_ELEMENTS_RELATIVE).setParameter('args', locator.marshall())
} else {
locator = by.checkedLocator(locator)
}
if (typeof locator === 'function') {
return this.findElementsInternal_(locator, this)
} else if (cmd === null) {
cmd = new command.Command(command.Name.FIND_ELEMENTS)
.setParameter('using', locator.using)View on GitHub (pinned to aa36b38e69)
Solutions
- Ensure the custom locator function returns a WebElement instance — use `return driver.findElement(By.css(selector))` or `return context.findElement(By.css(selector))` inside the function, not the raw selector or element data.
- If the locator returns an array, confirm every element in the array is a WebElement instance (the code will take result[0]).
- Add a return-type assertion or logging inside the locator function to verify the value before it reaches findElementInternal_.
- If you only need the element ID or raw data, use a different API (executeScript) instead of treating it as a WebElement locator.
Example fix
// before
driver.findElement(function(driver) {
return driver.executeScript('return document.querySelector("#foo");')
// executeScript returns a raw element or null, not a WebElement
})
// after
driver.findElement(function(driver) {
return driver.findElement(By.id('foo')) // returns a WebElement
}) Defensive patterns
Strategy: type-guard
Type guard
const { WebElement } = require('selenium-webdriver')
function isWebElement(v) {
return v instanceof WebElement
}
// Inside a custom locator:
// const result = ...; if (!isWebElement(result)) throw new Error('locator bug') Try / catch
try {
const el = await driver.findElement(customLocatorFn)
} catch (e) {
if (e instanceof TypeError && /Custom locator/.test(e.message)) {
// fix the locator to return a WebElement
} else throw e
} Prevention
- Custom locator functions must return a WebElement or array of WebElements — never primitives or plain objects.
- Use driver.findElement(By...) inside custom locators, not executeScript with raw DOM returns.
- Add a type assertion at the end of custom locator functions during development.
When it happens
Trigger: Defining a custom locator function (a function passed where a Locator is expected, e.g. driver.findElement(fn)) that returns a primitive, a plain object, a string, a Promise resolving to a non-WebElement, or undefined. The instanceof WebElement check fails on any such return.
Common situations: A custom locator returns a raw element ID or a JSON object instead of a WebElement wrapper; a locator function has a code path that returns undefined or null on an edge case; a developer misreads the locator API and returns a CSS selector string instead of performing the lookup.
Related errors
- Cannot locate an element with provided parameters
- CDP support for Firefox is removed. Please switch to WebDriv
- Downloads must be enabled in options
- events should be string or string array
- browsingContexts should be string or string array
AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14).
Data as JSON: /api/errors/0c4326d144ab2468.
Report an issue: GitHub.