Selenium has revolutionized web automation by empowering testers to streamline their workflows and improve test coverage. However, like any powerful tool, Selenium can sometimes throw curveballs in the form of unexpected exceptions.

This blog will explore a common Selenium error: org.openqa.selenium.StaleElementReferenceException, which means the locator to the element is no longer on the page.

Whether you’re a seasoned automation engineer or just starting your Selenium journey, you’ll gain valuable insights to troubleshoot effectively and write more robust test scripts in this blog.

What is ‘org.openqa.selenium.StaleElementReferenceException’?

The StaleElementReferenceException tells you that you are trying to interact with a web element that is no longer valid or present in the DOM (Document Object Model). A “stale element” means that the reference to the element you previously found on the page is no longer valid.

Think of it like having an old phone number for a friend. If they change their number, your saved contact becomes useless. You’ll need to get their new number to call them.

Reasons for StaleElementReferenceException

Let’s take a look at the main reasons why this exception occurs:

DOM Changes Dynamically

Modern websites often update parts of the page dynamically using JavaScript without requiring a full page reload. If the element you’re working with gets replaced or refreshed during such an update, the reference to that element becomes invalid.

Page Navigation or Reload

When the page navigates or reloads, the entire DOM is rebuilt, and any previously located elements become invalid.

Time Delay Between Locating and Using the Element

If there’s a significant delay between finding an element and interacting with it, the DOM may change during that time which then makes the element stale.

JavaScript or AJAX Actions

AJAX calls can update parts of the page asynchronously without a full reload. If you interact with an element before the update is complete or after it has been replaced, the exception will occur.

Element Is Removed from the DOM

If the element you’re interacting with is explicitly removed from the DOM (e.g., by a script), the reference becomes invalid.

How to Handle Stale Element Exception in Selenium

Re-locate the Element Before Interaction

If the DOM changes after you’ve located an element, you’ll need to find it again to get an updated reference. For example, if we look at a dynamic table, then after refreshing it, we need to re-locate the element.
driver.findElement(By.id("refresh")).click(); // Refresh the table
WebElement newRow = driver.findElement(By.id("row3")); // Re-locate new row
newRow.click();

Use Explicit Waits to Wait for DOM Stability

The DOM may take some time to update. Explicit waits ensure that Selenium interacts with the element only after it’s ready.

Here’s a code snippet to help explain how you can use a wait to ensure the content is visible before interacting.
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement content = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("content")));
content.click();

Handle the Exception with a Retry Mechanism

If you suspect the DOM is changing and causing stale references, retry the action to give the test a chance to re-locate the element after a short delay.

For example, if you have a button that reloads dynamically and causes stale references, then you can use a try-catch block to retry.
for (int i = 0; i < 3; i++) {
  try {
    WebElement button = driver.findElement(By.id("submit")); // Locate button
    button.click(); // Try clicking
    break; // Exit loop if successful
  } catch (StaleElementReferenceException e) {
    Thread.sleep(1000); // Wait before retrying
  }
}

Avoid Storing Element References for Too Long

Storing an element in a variable and using it later increases the risk of the DOM changing. Instead, locate the element immediately before interacting with it. Though this may be against standard procedures for some, it can help avoid this problem.

Synchronize Your Test with JavaScript or AJAX Actions

If your app uses JavaScript or AJAX to update the DOM asynchronously, waiting for those updates ensures the element remains valid.

Consider the example of typing into a search bar for results. You are more likely to get a successful test run if you wait for the suggestions to update before interacting.
driver.findElement(By.id("search")).sendKeys("query"); // Type in search
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement updatedSuggestion = wait.until(ExpectedConditions.elementToBeClickable(By.id("s2")));
updatedSuggestion.click();

Switch Back to the Correct Frame or Window

If you switch away from a frame or window containing your element, its reference becomes invalid. Switching back and re-locating the element ensures it’s valid.

For example:
driver.switchTo().frame("frame1"); // Switch to frame 1
WebElement button = driver.findElement(By.id("button1")); // Re-locate button
button.click();

Ensure Stable Locators for Elements

Dynamic locators (like IDs that change) make it hard to reliably interact with elements. Using stable locators ensures Selenium can always find the right element.

Handle Elements Removed from the DOM

If an element is removed from the DOM (e.g., a disappearing popup), ensure it’s still present before interacting with it.

Conclusion

While exceptions can be frustrating, they often help us learn more about the way we write test scripts. By understanding what the exception is trying to tell us and taking corrective measures, we can create reliable test scripts that run without giving flakey results.

More Like This