End-to-end Testing
7 min read

Everything you need to know about NoSuchElementException in Selenium

Learn how to deal with NoSuchElementException and other common Selenium WebDriver exceptions.

Antonello Zanini
Published July 29, 2022

Most web tests involve interacting with elements on a web page. This would not possible without first locating and retrieving these elements on the page. When the process of locating the elements of interest in the web page fails, Selenium throws a NoSuchElementException. This represents one of the most common Selenium exceptions, which is why it is so important to know about it and how to handle it correctly.

In this article, you will learn what a NoSuchElementException is, what the most common causes behind this exception are, and everything you need to know to handle it with Selenium WebDriver in Java.

What is a NoSuchElementException in Selenium?

NoSuchElementException is one of the most common exceptions in Selenium WebDriver, and it is thrown when an HTML element cannot be found. A NoSuchElementException occurs when the Selenium locator strategy defined is unable to find the desired HTML element in the web page.

NoSuchElementException derives from NotFoundException and is thrown by WebDriver.findElement and WebElement.findElement as below:

import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;

public class Main {
    public static void main(String[] args) {
        // setting the system property for the Chrome Driver
        System.setProperty("webdriver.chrome.driver", "<the_path_to_your_chrome_driver>");

        // initializing the Selenium WebDriver ChromeDriver class
        WebDriver driver = new ChromeDriver();

        driver.get("<your_url>");

        // trying to retrieve the "foo-button" HTML element
        WebElement fooButton = driver.findElement(By.id("foo-button");

        // ...
    }
}

When Selenium is not able to locate the HTML element with id “foo-button”, the following NoSuchElementException is thrown:

Exception in thread "main" org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":"#foo\-button"}

There are a few reasons why a NoSuchElementException can occur. Let’s now delve into them.

When Does NoSuchElementException Occur in a Selenium Test?

There are two main reasons for a NoSuchElementException:

How To Handle NoSuchElementException in Selenium?

There are two ways to deal with NoSuchElementException.

Using WebDriverWait

WebDriverWait allows you to wait for an HTML element to satisfy a specific condition defined through the ExpectedConditions class. For example, you can use it to wait some seconds until the HTML element you are looking for is present in the DOM as below:

// defining a locator for the HTML element with id = "foo-button"
By locator = By.id("foo-button");

// waiting up to 10 seconds until the "foo-button" HTML element is loaded into the DOM
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(ExpectedConditions.presenceOfElementLocated(locator));

// retrieving "foo-button" HTML element
WebElement fooButton = driver.findElement(locator);

// ...

This avoids a NoSuchElementException due to incomplete page loading. If the “foo-button” HTML element is not displayed in 10 seconds after calling the until() method, then a TimeoutException will be thrown. This exception will be introduced later.

Consider that the approach presented above may not be sufficient when dealing with AJAX calls. This is especially true when it comes to web apps developed in React, Vue, or Angular that make heavy use of API calls to retrieve data. In this scenario, you may need a more sophisticated approach involving a polling process. You can implement it as follows:

// defining a locator for the HTML element with id = "foo-button"
By locator = By.id("foo-button");

// waiting 10 seconds for the "foo-button" HTML element to be present on the page, and
// checking for its presence after 5 seconds sleep
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10), Duration.ofSeconds(5));
wait.until(ExpectedConditions.presenceOfElementLocated(locator));

// retrieving "foo-button" HTML element
WebElement fooButton = driver.findElement(locator);

// ...

The third parameter passed to WebDriverWait defines the duration of the sleep time between polls.

Notice that WebDriverWait ignores NotFoundExceptions thrown by the until() method by default, but immediately propagates all other exceptions. Therefore, also NoSuchElementException cannot be thrown by until() when calling it on a WebDriverWait instance.

Using more reliable selectors

The Selenium By class allows you to define the locator strategy that Selenium will apply to find HTML elements within a web document. When Selenium fails to find the HTML element identified with the By condition, a NoSuchElementException is thrown.

By offers several ways to locate an HTML element, but some are more reliable than others. For example, retrieving an HTML element based on its class attribute may not be a good strategy. This is because CSS classes are attributes that can easily change over time.

// retrieving the HTML element with class = "foo-align-right"
WebElement fooElement = driver.findElement(By.className("foo-align-right"));

If the layout of the web page changes or the “foo-align-right” class name is renamed, this line of code will throw a NoSuchElementException.

If you want your Selenium tests to be robust to changes in the target web pages, you need to use more reliable selectors. When it comes to defining selectors, you should prefer IDs to classes. The id attribute of an HTML element identifies it uniquely and is unlikely to change over time.

// retrieving the HTML element with id = "foo-button"
WebElement fooElement = driver.findElement(By.id("foo-button"));

In this case, the selector used to retrieve the HTML element is more reliable.

In general, you should always try to use selectors and locator strategies that are based on the distinctive priorities of an HTML element. Styling and placement might change many times over time, and relying on them forces you to update your tests to avoid NoSuchElementExceptions.

Other Common Selenium Exceptions That Can Occur

Let’s take a look at the three most common Selenium exceptions remaining.

InvalidSelectorException

InvalidSelectorExceptionis thrown by By when the selector passed as a parameter is a CSS or XPath expression that is syntactically invalid. You can avoid it by replacing the selector string used inBy condition with a valid expression.

Example:

// using an invalid CSS selector expression
WebElement fooButton = driver.findElement(By.cssSelector("/foo-button");

This is the InvalidSelectorException error that snippet would cause:

Exception in thread "main" org.openqa.selenium.TimeoutException: Expected condition failed: waiting for element to be clickable: By.cssSelector: @foo-button

ElementNotInteractableException

ElementNotInteractableException is thrown when an HTML element is present in the DOM but is in a state that cannot be interacted with. Note that this includes an HTML element that is hidden, or whose center point can not be scrolled into the browser viewport.

For example, ElementNotInteractableException is thrown when calling the click() method on a Selenium WebElement you momentarily cannot interact with. In this case, you can avoid the exception by employing the ExpectedCondition.elementToBeClickable method combined with WebDriverWait as below:

// defining a locator for the HTML element with id = "foo-button"
By locator = By.id("foo-button");

// waiting up to 10 seconds for the "foo-button" HTML element to be clickable
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(ExpectedConditions.elementToBeClickable(locator));

// retrieving "foo-button" HTML element and clicking it
WebElement fooButton = driver.findElement(locator);
fooButton.click()

If the fooButton element is in a non-interactable state, the last line would cause the following error:

Exception in thread "main" org.openqa.selenium.ElementNotInteractableException: element not interactable

TimeoutException

TimeoutException is thrown when a command does not complete in enough time. For example, when this exception occurs when an until() method on a WebDriverWait instance does not satisfy the expected conditions in the given time.

Example:

// defining a locator for the HTML element with id = "foo-button"
By locator = By.id("foo-butyon");

// waiting 10 seconds for the "foo-button" HTML element to be present on the page, and
// checking for its presence after 5 seconds sleep
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10), Duration.ofSeconds(5));
wait.until(ExpectedConditions.presenceOfElementLocated(locator));

// retrieving "foo-button" HTML element
WebElement fooButton = driver.findElement(locator);

// ...

Notice the typo introduced in the first line in the By condition. This would cause until() to fail and the following TimeoutException error as a result:

Exception in thread "main" org.openqa.selenium.TimeoutException: Expected condition failed: waiting for presence of element located by: By.id: foo-butyon (tried for 10 second(s) with 5000 milliseconds interval)

Conclusion

In this article, you learned that Selenium WebDriver is a powerful tool to perform automated tests on web applications, what NoSuchElementException is and when it occurs, and how to handle it in Java. Considering how frequent the NoSuchElementException is, understanding how it happens and being able to use handle it properly is critical to building robust Selenium WebDriver tests. Here you learned everything you need to know to interact with it and other common Selenium exceptions.

Try Reflect: A testing platform with better defaults

Reflect is a no-code testing tool that lets you avoid the tedium associated with other testing tools. Reflect has built-in logic to detect and wait for operations to complete before proceeding to the next step. Not only does this help reduce test flakiness, but it also makes test creation a lot faster and easier.

Stop struggling with flaky tests — try it for free.

Get started with Reflect today

Create your first test in 2 minutes, no installation or setup required. Accelerate your testing efforts with fast and maintainable test suites without writing a line of code.

Copyright © 2022 Reflect Software Inc. All Rights Reserved.