Selenium Errors and Exceptions
Almost every Selenium failure comes down to a handful of exceptions, and most of them have the same three root causes. This guide helps you identify the error in seconds, understand why it happened, and apply the right fix — with Java code — instead of adding another Thread.sleep().
Paste your error message into the Selenium Exception Lookup tool for an instant explanation, or use the table below.
Find Your Error
| Error message contains… | What it means | Full fix guide |
|---|---|---|
stale element reference: element is not attached to the page document |
The element was re-rendered and your reference is no longer valid | StaleElementReferenceException |
no such element: Unable to locate element |
Selenium searched the current context but found nothing | NoSuchElementException |
element click intercepted … Other element would receive the click |
Something is covering or overlapping your element | See ElementClickInterceptedException |
Expected condition failed: waiting for… |
The expected wait condition never became true | TimeoutException |
element not interactable |
Selenium found the element, but it is hidden, disabled, or has no usable size | ElementNotInteractable |
This version of ChromeDriver only supports Chrome version X |
ChromeDriver and the browser versions do not match | SessionNotCreatedException |
NullPointerException on a @FindBy field |
PageFactory.initElements() was not called |
NullPointerException with Selenium PageFactory |
NoClassDefFoundError / ClassNotFoundException |
A class is missing at runtime, or its initialization failed | ClassNotFoundException vs NoClassDefFoundError |
matches more than one step definition |
Duplicate Cucumber step definitions exist | Ambiguous and Undefined Steps |
Passes locally, fails in Jenkins |
There is likely an environment difference involving headless mode, viewport, timing, or test data | CI-Only Selenium Failures |
Selenium Exceptions List (Selenium 4)
Every exception below is a real class in Selenium 4.25 (checked in the library itself), and all of them extend WebDriverException. Most live in org.openqa.selenium. Note that ElementNotVisibleException and ElementNotSelectableException, still listed in many older tutorials, no longer exist in Selenium 4 — those situations now throw ElementNotInteractableException.
| Exception | Parent class | What it means | Usual fix |
|---|---|---|---|
NoSuchElementException | NotFoundException | No element matches the locator (yet) | Wait for it; check the locator, frame and timing |
StaleElementReferenceException | WebDriverException | The element was removed or re-rendered after you found it | Find it again; store locators, not WebElements |
ElementClickInterceptedException | ElementNotInteractableException | Another element (overlay, spinner, banner) is covering it | Wait for the overlay to disappear, scroll, or close the banner |
ElementNotInteractableException | InvalidElementStateException | The element exists but can't be used (hidden, zero size, off-screen) | Wait until it's visible/clickable; use the visible element |
InvalidElementStateException | WebDriverException | Action not allowed in its state (e.g. typing into a disabled field) | Check enabled/readonly state first |
TimeoutException | WebDriverException | An explicit wait or page load ran out of time | Check the condition and timeout; find why the app is slow |
NoSuchFrameException | NotFoundException | The frame to switch to doesn't exist | Wait for the frame: frameToBeAvailableAndSwitchToIt |
NoSuchWindowException | NotFoundException | The window/tab was closed or the handle is wrong | Re-read getWindowHandles() |
NoAlertPresentException | NotFoundException | You switched to an alert that isn't there | Wait for alertIsPresent() |
UnhandledAlertException | WebDriverException | An alert is open and blocks other commands | Accept or dismiss the alert first |
NoSuchShadowRootException | NotFoundException | The element has no shadow root | Check the host element before getShadowRoot() |
InvalidSelectorException | WebDriverException | The CSS or XPath syntax is invalid (or XPath returns non-elements) | Fix the selector; test it in DevTools first |
InvalidArgumentException | WebDriverException | Bad argument, e.g. a URL without http://, or a file path that doesn't exist | Check the value you pass |
JavascriptException | WebDriverException | The script run with JavascriptExecutor threw an error | Fix the script; check the browser console |
ScriptTimeoutException | TimeoutException | An async script didn't finish in time | Raise scriptTimeout or fix the script |
SessionNotCreatedException | WebDriverException | The browser couldn't start (driver/browser version mismatch, bad options) | Update Selenium (Selenium Manager matches drivers); check options |
NoSuchSessionException | WebDriverException | Command sent after quit() or after the browser crashed | Don't reuse a quit driver; one driver per test |
MoveTargetOutOfBoundsException | WebDriverException | Actions moved the mouse outside the viewport (package org.openqa.selenium.interactions) | Scroll the element into view first |
UnableToSetCookieException | WebDriverException | The cookie couldn't be set | Open a page on the cookie's domain first |
InvalidCookieDomainException | WebDriverException | The cookie's domain doesn't match the current page | Navigate to the right domain before addCookie |
UnexpectedTagNameException | WebDriverException | new Select(el) on an element that isn't <select> (package support.ui) | Use clicks for custom dropdowns |
Because they share a parent, you can catch a group at once: catch (NotFoundException e) covers missing elements, frames, windows, alerts and shadow roots; catch (WebDriverException e) covers everything above.
The Selenium Exception Decision Tree
Most Selenium failures can be diagnosed quickly if you ask a few questions in the right order.
1. Did Selenium Find the Element?
- No →
NoSuchElementException→ Check the locator, timing, or whether the element is inside an iframe. - Yes → Move to the next question.
2. Can Selenium Interact With It?
- No, it is hidden or disabled →
ElementNotInteractableException→ Check the element state and wait condition. - No, something is covering it →
ElementClickInterceptedException→ Check for overlays, loaders, modals, or sticky headers. - No, the reference is no longer valid →
StaleElementReferenceException→ Locate the element again. - Yes → Move to the next question.
3. Did It Work Locally but Fail in CI?
If the test passes locally but fails in Jenkins or another CI environment, investigate:
- Headless browser behavior
- Browser viewport size
- Different execution speed
- Environment configuration
- Missing test data
- Authentication or session differences
- Browser and driver versions
See Debugging in CI for a practical approach.
The Four "Can't Find / Can't Use" Selenium Exceptions
Understanding the difference between these exceptions clears up a large amount of Selenium debugging confusion.
| Exception | Meaning | Usual Cause |
|---|---|---|
NoSuchElementException |
Selenium could not find the element | Locator, timing, or iframe |
TimeoutException |
The wait condition never became true | Wrong condition, slow application, or application failure |
ElementNotInteractableException |
Selenium found the element but cannot interact with it | Element is hidden, disabled, or otherwise unavailable |
ElementClickInterceptedException |
Selenium found the element, but another element is covering it | Overlay, modal, loader, sticky header, or overlapping element |
The progression itself is useful for diagnosis.
For example, if you fix a NoSuchElementException and then receive an ElementNotInteractableException, that is actually useful progress. You have moved from a locator problem to an element-state problem.
The Three Root Causes Behind Most Selenium Failures
1. Timing
Your automation script may be executing faster than the web application.
For example, Selenium may attempt to click a button immediately after navigation while the application is still loading it.
The solution is generally not to add Thread.sleep().
Instead, use condition-based explicit waits that adapt to different machine speeds and application response times.
You can also try the Selenium Wait Simulator to understand visually how different wait strategies behave.
2. The Wrong Wait Condition
Different Selenium conditions answer different questions.
For example:
presenceOfElementLocated means that Selenium found the element in the DOM. It does not necessarily mean that the element is visible or ready to be clicked.
If you use the wrong condition, the wait can finish while the element is still unusable, resulting in another exception.
| You want to… | Recommended wait |
|---|---|
| Read text or assert on an element | visibilityOfElementLocated |
| Click an element | elementToBeClickable |
| Read an attribute | presenceOfElementLocated |
| Wait for a loader to disappear | invisibilityOfElementLocated |
Choosing the correct condition makes tests more reliable and makes failures easier to understand.
3. Caching WebElements
Storing WebElement objects in Page Objects or collections can create references that become invalid when the DOM changes.
For example:
// ❌ Caches a WebElement reference.
// The reference can become stale after a DOM re-render.
@FindBy(id = "user")
private WebElement user;
A more resilient approach is to store the locator and find the element when it is needed:
// ✅ Store the locator and resolve the element when needed.
private final By user = By.id("user");
This approach reduces problems caused by stale references and can also make Page Objects easier to maintain.
Code Fixes for the Most Common Selenium Exceptions
NoSuchElementException — Wait and Check for Iframes
A NoSuchElementException does not always mean that the locator is incorrect.
The element may be:
- Not rendered yet
- Inside an iframe
- In a different browsing context
- Loaded after an asynchronous operation
For an element inside an iframe, switch to the iframe first:
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
// If the element is inside an iframe, switch first.
wait.until(
ExpectedConditions.frameToBeAvailableAndSwitchToIt(
By.id("payment-frame")
)
);
WebElement cardNumber = wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("card-number")
)
);
cardNumber.sendKeys("4111111111111111");
driver.switchTo().defaultContent(); // Return to the main page.
Always remember that Selenium searches within the current browsing context. If an element belongs to an iframe, the driver must be switched into that frame before Selenium can locate it.
StaleElementReferenceException — Locate the Element Again
A StaleElementReferenceException occurs when Selenium has a reference to an element that is no longer attached to the current DOM.
This often happens when:
- The page is refreshed.
- A component is re-rendered.
- An AJAX request replaces an element.
- A table is dynamically updated.
- Navigation causes the DOM to change.
Instead of keeping a cached list of elements, locate the elements again when required.
By rows = By.cssSelector("table#orders tbody tr");
int count = driver.findElements(rows).size();
for (int i = 0; i < count; i++) {
// Re-find the elements on every iteration
// instead of using a cached list.
WebElement row = driver.findElements(rows).get(i);
row.findElement(By.cssSelector(".view")).click();
driver.navigate().back();
}
The important principle is:
Do not assume that a WebElement reference remains valid after the DOM changes.
ElementClickInterceptedException — Wait for the Overlay to Disappear
An ElementClickInterceptedException usually means Selenium found the target element, but another element is currently positioned above it.
Common causes include:
- Loading overlays
- Modals
- Cookie banners
- Sticky headers
- Dropdown menus
- Animations
- Other overlapping elements
A condition-based wait can solve many of these situations:
WebDriverWait wait = new WebDriverWait(
driver,
Duration.ofSeconds(10)
);
wait.until(
ExpectedConditions.invisibilityOfElementLocated(
By.cssSelector(".loading-overlay")
)
);
wait.until(
ExpectedConditions.elementToBeClickable(
By.id("submit")
)
).click();
If a sticky header is covering the element, you can scroll it into the center of the viewport:
WebElement element = driver.findElement(By.id("submit"));
((JavascriptExecutor) driver).executeScript(
"arguments[0].scrollIntoView({block: 'center'});",
element
);
However, JavaScript should not be used as a shortcut to bypass a genuine user-facing problem. First determine why the element cannot be clicked normally.
SessionNotCreatedException — Let Selenium Manage the Driver
A common SessionNotCreatedException occurs when the browser and driver versions are incompatible.
For example, you may see an error indicating:
This version of ChromeDriver only supports Chrome version X
Since Selenium 4.6, Selenium Manager can automatically manage browser drivers in many common setups.
If your project still contains hard-coded driver paths such as:
System.setProperty(
"webdriver.chrome.driver",
"path/to/chromedriver"
);
consider updating your Selenium setup and allowing Selenium Manager to handle driver management where appropriate.
For version-mismatch troubleshooting, see SessionNotCreatedException and ChromeDriver Version Mismatch.
The 60-Second Selenium Diagnosis
Before changing your automation code, use the browser's DevTools to determine whether the element actually exists.
Open DevTools → Console and run:
document.querySelectorAll("#your-locator").length
The result provides a quick diagnostic signal.
| Result | Meaning |
|---|---|
0 |
The element is not currently in the DOM. Check the locator, timing, or rendering. |
1 |
The element exists. Investigate timing, visibility, state, or browsing context such as an iframe. |
2+ |
Multiple elements match the selector. One or more may be hidden or may not be the intended target. |
You can also check whether the page contains iframes:
document.querySelectorAll("iframe").length
If the result is greater than 0, investigate whether the target element is inside an iframe.
This quick check can save significant debugging time.
For additional locator practice, try the CSS & XPath Selector Playground.
Debugging Selenium Failures in CI
When Selenium runs in CI, you often cannot see the browser. That means your test needs to collect enough diagnostic information to explain what happened.
Set a Realistic Headless Viewport
Headless browser execution can behave differently from a normal local browser session.
Set an explicit window size:
ChromeOptions options = new ChromeOptions();
options.addArguments(
"--headless=new",
"--window-size=1920,1080"
);
WebDriver driver = new ChromeDriver(options);
Using a predictable viewport can help expose differences caused by responsive layouts and elements that move at smaller screen sizes.
Capture Screenshots and Page Source
When a test fails, capture both a screenshot and the page source.
For example, with TestNG:
@AfterMethod
public void captureOnFailure(ITestResult result) throws IOException {
if (result.getStatus() == ITestResult.FAILURE) {
String name =
result.getMethod().getMethodName()
+ "_"
+ System.currentTimeMillis();
Path dir = Paths.get("target", "failures");
Files.createDirectories(dir);
File shot =
((TakesScreenshot) driver)
.getScreenshotAs(OutputType.FILE);
Files.copy(
shot.toPath(),
dir.resolve(name + ".png")
);
Files.writeString(
dir.resolve(name + ".html"),
driver.getPageSource()
);
}
}
The page source can be particularly useful for locator-related failures.
A screenshot tells you what the browser visually displayed, while the page source can show whether the expected element existed in the DOM and what its actual structure was at the time of failure.
In Jenkins, archive the target/failures directory as a build artifact so the diagnostic files remain available after the test execution finishes.
Selenium Errors That May Actually Be Application Bugs
Not every Selenium exception means the test is wrong.
Before changing the automation, ask whether the failure represents something a real user would also experience.
| Symptom | What it may actually mean |
|---|---|
ElementClickInterceptedException caused by a modal |
A real user may also be unable to click the underlying element |
ElementNotInteractableException with isEnabled() returning false |
Application validation may be correctly preventing the action |
| Element disappears after a user action | The application behavior itself may be incorrect |
For example, using JavaScript to click an element can bypass an overlay.
The automation may then pass even though a real user cannot click the button.
Always ask:
Could a real user perform this action successfully?
If the answer is no, investigate whether the problem is actually an application defect rather than simply modifying the test to force it to pass.
Should You Just Add Retries?
Retry mechanisms such as TestNG's IRetryAnalyzer can sometimes keep a pipeline moving when transient failures occur.
However, retries can also hide flaky tests.
For example:
Test fails → Retry → Test passes
The pipeline may appear green, but the underlying problem still exists.
Use retries carefully and treat them as a temporary mitigation rather than a replacement for root-cause analysis.
When retries are used:
- Log every retry.
- Track the frequency of retries.
- Investigate recurring failures.
- Fix timing and synchronization problems.
- Avoid allowing retries to hide persistent defects.
For more practical examples, see Automation Decisions & Flaky Tests.
From Real Projects
Across my 4+ years in testing I've written and maintained Selenium WebDriver scripts in Java with TestNG on Canolog, an automotive dealership management system, and on Testsigma, a low-code test automation platform. Most of the exceptions on this page showed up for me when we moved from running tests one by one to batch, group, parallel and cross-browser runs on Chrome and Firefox: a locator or wait that was fine in a single run started failing when timing changed. What helped most was keeping every locator inside POM classes, so a fix happened in one place, and reviewing each other's scripts before they joined the regression suite.
📚 Official documentation: Selenium docs: Understanding common errors · Selenium docs: Waiting strategies
Exception Handling in Selenium: try-catch the Right Way
Every Selenium exception extends WebDriverException, which is a RuntimeException. That's why the compiler never forces you to catch them. It also means catching them is a choice you should make carefully.
- Don't catch to hide a failure. An empty
catchturns a real bug into a passing test. - Use
findElementsfor "is it there?" checks instead of catchingNoSuchElementException. - Use explicit waits for timing problems, so you rarely need a catch at all.
- Retry once, narrowly, only for exceptions that a fresh lookup can fix, such as
StaleElementReferenceException. - When you do catch, add context and rethrow: take a screenshot, log the locator and URL, then let the test fail.
// Presence check without try-catch
public boolean isPresent(By locator) {
return !driver.findElements(locator).isEmpty();
}
// Narrow retry for a stale element
public void clickWithRetry(By locator) {
for (int attempt = 1; attempt <= 2; attempt++) {
try {
wait.until(ExpectedConditions.elementToBeClickable(locator)).click();
return;
} catch (StaleElementReferenceException e) {
if (attempt == 2) throw e; // still stale: let the test fail
}
}
}
Frequently Asked Questions
What are the most common Selenium exceptions?
Some of the most common Selenium exceptions include:
NoSuchElementExceptionStaleElementReferenceExceptionElementClickInterceptedExceptionTimeoutExceptionElementNotInteractableExceptionSessionNotCreatedException
Each exception points toward a different category of problem, so identifying the exact exception is an important first step in debugging.
What causes most Selenium failures?
Many Selenium failures can be traced to three recurring areas:
- Timing — the automation runs before the application is ready.
- Incorrect wait conditions — the test waits for the wrong state.
- Cached WebElement references — the DOM changes after Selenium stores the element reference.
Understanding these patterns can make Selenium debugging much faster.
How do I stop Selenium tests from being flaky?
Start by replacing arbitrary sleeps with condition-based explicit waits.
Also:
- Use reliable locators.
- Store
Bylocators rather than unnecessary cachedWebElementreferences. - Keep test data independent.
- Use appropriate wait conditions.
- Control browser viewport size in CI.
- Capture screenshots and page source on failure.
- Investigate recurring failures instead of relying heavily on retries.
Why do Selenium tests fail only in Jenkins?
A test can pass locally and fail in Jenkins because the execution environment is different.
Common causes include:
- Headless browser execution
- Different viewport size
- Different browser or driver version
- Slower CI infrastructure
- Missing cookies or local storage
- Missing test data
- Different environment configuration
- Timing differences
Start by setting an explicit browser window size such as:
--window-size=1920,1080
Then compare the page source and screenshots from the CI failure with the local execution.
For more information, see Selenium Tests Passing Locally but Failing in Jenkins.
Should I use a JavaScript click to fix intercepted clicks?
Usually, no.
A JavaScript click can bypass the normal browser interaction model and may cause the test to pass even though a real user cannot click the element.
First investigate:
- Overlay
- Modal
- Loader
- Sticky header
- Animation
- Incorrect element state
If a real user cannot perform the action, the problem may be an application defect rather than a Selenium issue.
What is the difference between NoSuchElementException and TimeoutException?
NoSuchElementException is typically thrown when Selenium cannot find an element using findElement() within the applicable implicit wait.
TimeoutException is thrown when an explicit wait such as WebDriverWait reaches its timeout while the expected condition remains false.
For example:
driver.findElement(By.id("login"));
may result in NoSuchElementException when the element cannot be found.
Whereas:
wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("login")
)
);
may result in TimeoutException if the element does not become visible before the timeout expires.
Should I mix implicit and explicit waits?
It is generally better to avoid mixing implicit and explicit waits because their interactions can make wait behavior harder to predict.
A common approach is to keep the implicit wait at zero and use explicit waits for specific conditions.
For a detailed comparison, see Implicit vs Explicit vs Fluent Wait.
Are Selenium exceptions checked or unchecked?
Unchecked. They all extend WebDriverException, which extends RuntimeException, so Java doesn't require a try-catch or a throws clause.
What is the parent class of all Selenium exceptions?
org.openqa.selenium.WebDriverException. Catching it catches every Selenium exception, which is why you should catch the specific one you expect instead.
How do you handle exceptions in Selenium WebDriver?
Prevent most of them with stable locators and explicit waits, check optional elements with findElements, retry once only for stale elements, and when you catch an exception, log details and a screenshot and rethrow it so the test still fails.
Related Reading
- The Complete Selenium WebDriver Guide — Complete Selenium learning path
- Selenium Waits — Understanding synchronization and explicit waits
- Selenium Locators and XPath — Build reliable Selenium locators
- Alerts, Frames & Windows: switchTo() Explained — Learn how to work with different browser contexts
- Selenium Scenario-Based Interview Questions — Practical Selenium interview preparation
- The Complete Jenkins Tutorial — CI/CD concepts for testers