TimeoutException in Selenium

Quick answer: a TimeoutException means your explicit wait's condition never became true — usually because you waited for the wrong condition. An ElementNotInteractableException means Selenium found the element but it's hidden, disabled, zero-size or off-screen. Match the wait condition to the action (elementToBeClickable before a click), and check isDisplayed() and isEnabled() before forcing anything.

Advertisement

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.