TimeoutException in Selenium
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 found something — it just couldn't proceed. That's the key difference from NoSuchElementException.
TimeoutException
What it means
Your WebDriverWait polled for the full timeout and the condition never became true. Note what the message tells you: the condition it was waiting for, and for how long. Read it — it names your bug.
The Causes
Wrong condition ⭐
The most common by far.
// 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 | Waits for | Use before |
|---|---|---|
presenceOfElementLocated |
In the DOM (may be invisible) | Reading attributes only |
visibilityOfElementLocated |
In DOM and visible | getText(), assertions |
elementToBeClickable ⭐ |
Visible and enabled | click() |
It genuinely takes longer than the timeout
Slow API, heavy page. Raise the timeout — but only after confirming it's not the wrong condition.
Wrong locator
The condition can never pass because nothing matches. TimeoutException is NoSuchElementException wearing a coat: the wait swallowed the "not found" and reported a timeout instead.
Wrong context
It's in an iframe you haven't switched to. Same story: it'll never appear.
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 built-ins don't fit
wait.until(d -> d.findElement(By.id("count")).getText().equals("5"));
⚠️ Don't mix implicit and explicit waits. Setting both makes timeouts unpredictable — Selenium's own docs warn against it. Pick explicit, set implicit to 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, opacity:0 |
| Zero size | Width or height is 0 |
| Disabled | <button disabled> |
| Off-screen | Outside the viewport (common in headless 800×600) |
| Not ready yet | Rendered but still animating in |
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 one matters. If isEnabled() is false, no amount of waiting helps — the app is telling you the button shouldn't be clicked yet. Usually a form validation you haven't satisfied. That's a real finding, not an automation problem.
Telling the Three Apart ⭐
| Exception | Selenium… | Means |
|---|---|---|
NoSuchElementException |
couldn't find it | Wrong locator, timing, or iframe |
TimeoutException |
Found nothing matching the condition in time | Wrong condition, or genuinely slow |
ElementNotInteractableException |
found it, can't use it | Hidden, disabled, zero-size, off-screen |
ElementClickInterceptedException |
Found it, something's on top | Overlay/popup/sticky header |
The progression is diagnostic: if you fix a NoSuchElement and now get ElementNotInteractableException, you've made progress — the element exists, so now it's 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.
The Interview Answer
"TimeoutException means the wait condition never became true in the timeout — most often because the condition was wrong, like waiting for presence and then clicking, when presence only means it's 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 —
elementToBeClickablebefore a click — and I checkisDisplayed(),isEnabled(), andgetSize()to see why, rather than just increasing the timeout, which only makes the failure slower."
FAQs
Why does my explicit wait time out when the element is right there?
Usually the wrong condition. 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 just makes the failure slower.
What's the difference between TimeoutException and NoSuchElementException?
NoSuchElement = the immediate lookup found nothing.
Timeout = a wait polled and the condition never came 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, or off-screen. Check isDisplayed(), isEnabled(), and getSize().
Can I mix implicit and explicit waits?
No. Mixing them causes unpredictable timeouts. Use explicit waits and leave implicit at zero.
Related
- 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