keepcalculator

06 Numbers and Powers

Stale Element Exceptions in Selenium Java: How to Fix

Card No. 06·51129 · Updated · Standard formula, shown below

This guide walks you through the most common causes of the StaleElementReferenceException in Selenium WebDriver with Java and gives you a practical, step-by-step approach to handle it reliably. You’ll learn why the exception happens, how to write a robust retry mechanism, and how to avoid it altogether in your test code.

What You’ll Need

  • Java 8 or higher
  • Selenium Java bindings (version 4.x recommended)
  • A WebDriver instance (ChromeDriver, GeckoDriver, etc.)
  • Basic knowledge of Java exceptions and try-catch blocks
  • JUnit or TestNG (optional, for test structure)

Step-by-Step

  1. Understand what causes the exception. A stale element means the element you located is no longer attached to the DOM. This typically happens after a page refresh, navigation, or JavaScript updates that replace the element. The WebDriver reference points to an old DOM node.
  2. Identify the exact line where it occurs. When the exception is thrown, look at the stack trace. It will point to a findElement call or an interaction like click(), sendKeys(), or getText(). Knowing the step helps you decide the best fix.
  3. Re-locate the element before each action. The simplest fix is to call driver.findElement(By.id("myId")) again right before you interact with it. This ensures you have a fresh reference. For example:
    WebElement button = driver.findElement(By.id("submit"));
    button.click(); // may throw stale
    // Instead:
    driver.findElement(By.id("submit")).click();
  4. Use a retry loop with explicit waits. If the element becomes stale intermittently, implement a small retry mechanism. Wrap the action in a loop that catches StaleElementReferenceException and retries after a short wait. Here’s a reusable helper:
    public void clickWithRetry(WebDriver driver, By locator, int maxRetries) {
        for (int i = 0; i < maxRetries; i++) {
            try {
                WebElement el = driver.findElement(locator);
                el.click();
                return;
            } catch (StaleElementReferenceException e) {
                // Wait a bit and try again
                try { Thread.sleep(500); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); }
            }
        }
        throw new StaleElementReferenceException("Element still stale after retries");
    }
  5. Combine with WebDriverWait for better reliability. Instead of a fixed sleep, use WebDriverWait to wait for the element to be present or visible before retrying. Example:
    public void clickWithWait(WebDriver driver, By locator) {
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
        for (int i = 0; i < 3; i++) {
            try {
                WebElement el = wait.until(ExpectedConditions.elementToBeClickable(locator));
                el.click();
                return;
            } catch (StaleElementReferenceException e) {
                // continue loop
            }
        }
    }
  6. Use a custom ExpectedCondition for complex scenarios. If you need to wait for an element to be stable (e.g., after an AJAX update), create a condition that returns true when the element is present and not stale. For example:
    public static ExpectedCondition<WebElement> elementIsStable(By locator) {
        return new ExpectedCondition<WebElement>() {
            public WebElement apply(WebDriver driver) {
                try {
                    WebElement el = driver.findElement(locator);
                    // Force a check that the element is usable
                    el.isEnabled();
                    return el;
                } catch (StaleElementReferenceException e) {
                    return null;
                }
            }
        };
    }
  7. Refresh the page and re-locate if necessary. In some cases, the page content changes completely (e.g., after a form submission). If retries fail, you may need to refresh the page and start the process over. Use driver.navigate().refresh() and then re-find the element.
  8. Store locators, not WebElement objects. A common mistake is storing a WebElement in a variable and reusing it later. Instead, always store the By locator and call findElement when needed. This avoids stale references entirely.
  9. Use Page Object Model (POM) with fresh lookups. In your page objects, return elements via methods that call findElement each time. This ensures you never hold a stale reference. For example:
    public WebElement getSubmitButton() {
        return driver.findElement(By.id("submit"));
    }
  10. Consider using JavaScript to interact when all else fails. If the element is stale because the DOM is being constantly updated, you can use JavascriptExecutor to click or set values directly. This bypasses the WebElement reference. Example:
    JavascriptExecutor js = (JavascriptExecutor) driver;
    js.executeScript("arguments[0].click();", driver.findElement(locator));

    Note: This should be a last resort as it doesn’t simulate user interaction as accurately.

Common Mistakes

  • Storing WebElement objects in fields or variables and reusing them after navigation or AJAX updates.
  • Using fixed sleeps (Thread.sleep) instead of explicit waits. This makes tests slow and flaky.
  • Catching the exception and doing nothing – silently swallowing the error without retrying or logging.
  • Using the same locator that is ambiguous – if multiple elements match, the one you get might be replaced by a different one.
  • Retrying too many times without a proper wait, causing CPU spin and still failing.

Tips

  • Use relative locators or unique attributes (like data-testid) to make locators more stable.
  • Always use WebDriverWait with expected conditions for dynamic content.
  • Log the exception details – include the locator and the current page URL to help debug.
  • Write a reusable utility class for handling stale elements so you don’t repeat code.
  • Keep your waits short (e.g., 5-10 seconds) to avoid slowing down your test suite.
  • Test on the same browser version you use in production to reduce inconsistencies.

Troubleshooting

  • If the retry loop still fails: Check if the element is inside an iframe. If so, you need to switch to the iframe before locating the element. Use driver.switchTo().frame() and then locate.
  • If the element is present but not interactable: The element might be covered by another element or disabled. Use WebDriverWait with elementToBeClickable instead of just presence.
  • If the exception occurs after a page load: Make sure you wait for the page to fully load using driver.manage().timeouts().pageLoadTimeout() or an explicit wait for a specific element on the new page.
  • If the locator finds multiple elements: Use findElements and pick the correct one based on index or attributes, or refine the locator.
  • If the issue is intermittent: Increase the retry count and add a small random delay between retries to avoid race conditions.

Frequently Asked Questions

What exactly is a stale element in Selenium?

A stale element is a WebElement reference that points to a DOM node that no longer exists. This can happen after the page is refreshed, navigated, or the element is re-rendered by JavaScript.

Why does StaleElementReferenceException happen even when I use WebDriverWait?

WebDriverWait waits for a condition to be true, but if the element becomes stale after the wait condition is met (e.g., during a click), the exception can still occur. That’s why you need a retry mechanism around the action itself.

Should I use Thread.sleep or WebDriverWait to handle stale elements?

Always prefer WebDriverWait. Thread.sleep is a fixed delay that can be too short or too long, making tests flaky. WebDriverWait polls the condition and proceeds as soon as it’s true.

Can I avoid stale elements entirely?

Yes, by always re-finding elements right before interacting with them, using locators instead of storing WebElement objects, and using Page Object Model with fresh lookups. This reduces the chance of stale references.

Is it safe to use JavaScript clicks to bypass stale elements?

It’s a workaround, but it doesn’t simulate real user interaction (like event handlers that fire on a real click). Use it only when other methods fail, and be aware that it may not trigger the same JavaScript events.

How many retries should I do?

Typically 2-3 retries with a short wait (500ms to 1 second) is sufficient. If it still fails, it’s likely a deeper issue with your locator or application behavior, so log and fail the test.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →