TimeoutException in Selenium
Quick answer: a
TimeoutExceptionmeans your explicit wait's condition never became true — usually because you waited for the wrong condition. AnElementNotInteractableExceptionmeans Selenium found the element but it's hidden, disabled, zero-size or off-screen. Match the wait condition to the action (elementToBeClickablebefore a click), and checkisDisplayed()andisEnabled()before forcing anything.
The Errors
org.openqa.selenium.TimeoutException:
Expected condition failed: waiting for visibility of element located by By.id: submit
(tried for 10 second(s) with 500 milliseconds interval)
org.openqa.selenium.ElementNotInteractableException:
element not interactable
Both mean Selenium got further than "couldn't find it" — it just couldn't proceed. That's the key difference from NoSuchElementException. (Note: this is Selenium's org.openqa.selenium.TimeoutException, not Java's java.util.concurrent.TimeoutException — check your import.)
TimeoutException
What it means
Your WebDriverWait polled for the full timeout and the condition never became true.
Read the message — it names your bug
- "waiting for visibility of element located by By.id: submit" — the exact condition and locator. Is visibility really what you needed?
- "tried for 10 second(s)" — the timeout you set.
- "with 500 milliseconds interval" — how often it checked (the default polling interval).
Before changing any code, ask: is this the right condition, for the right locator, in the right frame?
The causes
1. Wrong condition ⭐ — by far the most common.
// You waited for PRESENCE (in the DOM), then clicked
wait.until(ExpectedConditions.presenceOfElementLocated(By.id("submit"))).click();
// 💥 element is in the DOM but hidden → passes the wait, fails the click
Presence ≠ visible ≠ clickable. Pick the condition that matches what you're about to do:
| Condition | Means | Use before |
|---|---|---|
presenceOfElementLocated |
In the DOM (may be invisible) | Reading attributes only |
visibilityOfElementLocated |
In the DOM and visible | getText(), assertions |
elementToBeClickable ⭐ |
Visible and enabled | click() |
invisibilityOfElementLocated |
Gone or hidden | Continuing after a spinner or overlay |
textToBePresentInElementLocated |
Element contains the text | Checking a status message |
urlContains |
Navigation finished | Asserting on the next page |
numberOfElementsToBe |
List has loaded fully | Counting search results or rows |
frameToBeAvailableAndSwitchToIt |
Iframe ready, and switches into it | Working inside an iframe |
2. Genuinely slow — a slow API or heavy page. Raising the timeout is fine here, but only after confirming it isn't cause 1.
3. Wrong locator — the condition can never pass because nothing matches. TimeoutException is NoSuchElementException wearing a coat: WebDriverWait ignores "not found" while polling and reports a timeout at the end. Check the locator in DevTools with document.querySelectorAll("#submit").length, or in the Selector Playground.
4. Inside an iframe — the element is in a frame you haven't switched to, so it will never appear in the main document. Use frameToBeAvailableAndSwitchToIt first.
The fixes
// ✅ Match the condition to the action
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(ExpectedConditions.elementToBeClickable(By.id("submit"))).click();
// ✅ Wait for the loader to GO, not just the button to appear
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.className("spinner")));
// ✅ Custom condition when the built-ins don't fit
wait.until(d -> d.findElement(By.id("count")).getText().equals("5"));
Need more control? Use FluentWait
FluentWait lets you choose the polling interval and which exceptions to ignore while waiting — useful for elements that are re-rendered repeatedly:
Wait<WebDriver> fluent = new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(15))
.pollingEvery(Duration.ofMillis(300))
.ignoring(NoSuchElementException.class)
.ignoring(StaleElementReferenceException.class);
WebElement result = fluent.until(d -> d.findElement(By.id("result")));
See the difference between the three wait types in Implicit vs Explicit vs Fluent Wait, or watch them play out in the Selenium Wait Simulator.
⚠️ Don't mix implicit and explicit waits. Setting both makes timeouts unpredictable — Selenium's own documentation warns against it. Use explicit waits and keep the implicit wait at zero.
ElementNotInteractableException
What it means
Selenium found the element, but it isn't in a state you can interact with.
The causes
| Cause | Why |
|---|---|
| Hidden | display:none, visibility:hidden or opacity:0 |
| Zero size | Width or height is 0 |
| Disabled | e.g. <button disabled> |
| Off-screen | Outside the viewport — common in headless mode's small default window |
| Not ready yet | Rendered but still animating in |
| Wrong match | Your locator matches two elements (e.g. a hidden mobile menu and the visible desktop one) and Selenium uses the first — the hidden one |
The fixes
// 1. Wait for clickable, not just present ⭐
wait.until(ExpectedConditions.elementToBeClickable(By.id("submit"))).click();
// 2. Scroll it into view
((JavascriptExecutor) driver).executeScript(
"arguments[0].scrollIntoView({block:'center'});", element);
// 3. Check WHY it's not interactable before forcing it
System.out.println("displayed: " + element.isDisplayed());
System.out.println("enabled: " + element.isEnabled());
System.out.println("size: " + element.getSize());
That third step matters. If isEnabled() is false, no amount of waiting helps — the application is telling you the button shouldn't be clicked yet, usually because a form validation isn't satisfied. That's a real finding, not an automation problem.
If your locator matches more than one element, pick the visible one — or better, make the locator more specific:
WebElement menu = driver.findElements(By.cssSelector(".nav-menu")).stream()
.filter(WebElement::isDisplayed)
.findFirst()
.orElseThrow(() -> new IllegalStateException("No visible menu found"));
In headless CI, set a real window size so elements aren't pushed off-screen: options.addArguments("--headless=new", "--window-size=1920,1080");. More in Test Passes Locally, Fails in Jenkins.
Avoid the JavaScript-click shortcut. executeScript("arguments[0].click();", el) clicks elements a real user can't reach — your test passes while the bug ships. Use it only when you've confirmed the element is interactable for users and Selenium's click is the problem.
Telling the Four Apart ⭐
| Exception | Meaning | Usual cause |
|---|---|---|
| NoSuchElementException | Couldn't find it | Wrong locator, timing or iframe |
| TimeoutException | The condition never became true in time | Wrong condition, or genuinely slow |
| ElementNotInteractableException | Found it, can't use it | Hidden, disabled, zero-size, off-screen |
| ElementClickInterceptedException | Found it, something is on top | Overlay, popup or sticky header — see Element Not Clickable at Point |
The progression is diagnostic: if you fix a NoSuchElement and now get ElementNotInteractableException, you've made progress — the element exists, so it's now a state problem, not a locator problem.
The Trap: Longer Timeouts
// ❌ The instinct
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(60));
This turns a 10-second failure into a 60-second failure. It doesn't fix anything — it just makes your suite slower at being wrong. If a 10-second wait times out, the condition is usually wrong, not slow. Check the condition before you touch the number, and keep one timeout value in your framework's config instead of scattering different numbers through the code.
The Interview Answer
"TimeoutException means the wait condition never became true within the timeout — most often because the condition was wrong, like waiting for presence and then clicking, when presence only means the element is in the DOM, not visible or enabled. ElementNotInteractableException means Selenium found the element but it's hidden, disabled, zero-size or off-screen. I match the condition to the action — elementToBeClickable before clicking, visibility before reading text — check isDisplayed and isEnabled before forcing anything, and I don't fix these by simply raising the timeout."
From Real Projects
My Selenium work — Java, TestNG and a POM-based hybrid framework on Canolog and Testsigma — involved running the same scripts in batch, group, parallel and cross-browser mode on Chrome and Firefox. That's where problems like the one on this page tend to surface: a script that passes alone can fail when timing, browser or execution order changes. Keeping locators in POM classes meant each fix happened in one place, and reviewing scripts before they joined the suite caught many issues early. Before raising a timeout, ask what the page is actually waiting for; waiting for the right condition fixes more timeouts than a longer timeout does.
📚 Official documentation: Selenium docs: Waiting strategies · Selenium docs: Understanding common errors
FAQs
Why does my explicit wait time out when the element is right there?
Usually the wrong condition — or the element is inside an iframe. presenceOfElementLocated passes while the element is still hidden; use visibilityOfElementLocated or elementToBeClickable.
Should I just increase the timeout?
Rarely. If 10 seconds isn't enough, the condition is usually wrong. A longer timeout only makes the failure slower.
What's the difference between TimeoutException and NoSuchElementException?
NoSuchElementException comes from an immediate findElement that found nothing. TimeoutException comes from a wait whose condition never became true — often the same underlying cause, reported differently.
Why is my element "not interactable" when I can see it?
It may be disabled, zero-size, still animating, off-screen — or your locator is matching a different, hidden copy of it. Check isDisplayed(), isEnabled() and getSize(), and how many elements your locator matches.
Can I mix implicit and explicit waits?
No. Mixing them causes unpredictable timeouts. Use explicit waits and leave the implicit wait at zero.
What is the default polling interval of WebDriverWait?
500 milliseconds. Use FluentWait (or pollingEvery on a WebDriverWait) if you need a different interval.
How do I wait for a spinner or loading overlay?
Wait for it to disappear with invisibilityOfElementLocated, then wait for your target to be clickable.
Related
- Selenium Errors & Exceptions: The Complete Troubleshooting Guide
- Selenium Waits — implicit vs explicit vs fluent
- NoSuchElementException — when it can't find it
- Element Not Clickable at Point — when something's on top
- Test Passes Locally, Fails in Jenkins — headless viewport issues
- Paste any error into the Selenium Exception Lookup