Common Errors
Diagnose and fix the most common Selenium errors and exceptions.
Understanding common Selenium errors helps you debug tests faster. This guide covers the most frequent exceptions and how to fix them.
NoSuchElementException
Cause: The element cannot be found in the DOM.
// ERROR: NoSuchElementException - Element not found// driver.findElement(By.id("nonexistent"));
// SOLUTIONS:
// 1. Add explicit wait - element may not be loaded yetWebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));WebElement element = wait.until( ExpectedConditions.presenceOfElementLocated(By.id("myElement")));
// 2. Check if element is in iframedriver.switchTo().frame("iframeName");WebElement element = driver.findElement(By.id("myElement"));
// 3. Verify locator in browser DevTools// Right-click element > Inspect > Check actual id/class/etc.
// 4. Handle dynamic IDs// Instead of: By.id("button_12345")// Use: By.cssSelector("[id^='button_']") // Starts with// Or: By.xpath("//button[contains(@id, 'button')]")# ERROR: NoSuchElementException - Element not found# driver.find_element(By.ID, "nonexistent")
# SOLUTIONS:
# 1. Add explicit wait - element may not be loaded yetfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)element = wait.until( EC.presence_of_element_located((By.ID, "myElement")))
# 2. Check if element is in iframedriver.switch_to.frame("iframeName")element = driver.find_element(By.ID, "myElement")
# 3. Verify locator in browser DevTools# Right-click element > Inspect > Check actual id/class/etc.
# 4. Handle dynamic IDs# Instead of: By.ID, "button_12345"# Use: By.CSS_SELECTOR, "[id^='button_']" # Starts with# Or: By.XPATH, "//button[contains(@id, 'button')]"// ERROR: NoSuchElementError - Element not found// await driver.findElement(By.id('nonexistent'));
// SOLUTIONS:
// 1. Add explicit wait - element may not be loaded yetconst { until } = require('selenium-webdriver');
const element = await driver.wait( until.elementLocated(By.id('myElement')), 10000);
// 2. Check if element is in iframeawait driver.switchTo().frame('iframeName');const element = await driver.findElement(By.id('myElement'));
// 3. Verify locator in browser DevTools// Right-click element > Inspect > Check actual id/class/etc.
// 4. Handle dynamic IDs// Instead of: By.id('button_12345')// Use: By.css("[id^='button_']") // Starts with// ERROR: NoSuchElementException - Element not found// driver.FindElement(By.Id("nonexistent"));
// SOLUTIONS:
// 1. Add explicit wait - element may not be loaded yetWebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));IWebElement element = wait.Until( d => d.FindElement(By.Id("myElement")));
// 2. Check if element is in iframedriver.SwitchTo().Frame("iframeName");IWebElement element = driver.FindElement(By.Id("myElement"));
// 3. Verify locator in browser DevTools// Right-click element > Inspect > Check actual id/class/etc.
// 4. Handle dynamic IDs// Instead of: By.Id("button_12345")// Use: By.CssSelector("[id^='button_']") // Starts withStaleElementReferenceException
Cause: The element reference is outdated because the DOM changed.
// ERROR: StaleElementReferenceException// The element was found, but the page refreshed or element was re-rendered
// WRONG - element reference becomes stale after page actionWebElement button = driver.findElement(By.id("submit"));driver.navigate().refresh(); // Page refreshedbutton.click(); // ERROR! Element is stale
// SOLUTION 1: Re-find the element after DOM changesWebElement button = driver.findElement(By.id("submit"));driver.navigate().refresh();button = driver.findElement(By.id("submit")); // Re-findbutton.click();
// SOLUTION 2: Use explicit wait for staleness then re-findWebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));WebElement element = driver.findElement(By.id("dynamic"));
// Wait until element becomes stale, then find new onewait.until(ExpectedConditions.stalenessOf(element));element = wait.until( ExpectedConditions.presenceOfElementLocated(By.id("dynamic")));
// SOLUTION 3: Retry patternpublic WebElement findWithRetry(By locator, int maxRetries) { for (int i = 0; i < maxRetries; i++) { try { WebElement element = driver.findElement(locator); element.isDisplayed(); // Verify element is valid return element; } catch (StaleElementReferenceException e) { if (i == maxRetries - 1) throw e; } } return null;}# ERROR: StaleElementReferenceException# The element was found, but the page refreshed or element was re-rendered
# WRONG - element reference becomes stale after page actionbutton = driver.find_element(By.ID, "submit")driver.refresh() # Page refreshedbutton.click() # ERROR! Element is stale
# SOLUTION 1: Re-find the element after DOM changesbutton = driver.find_element(By.ID, "submit")driver.refresh()button = driver.find_element(By.ID, "submit") # Re-findbutton.click()
# SOLUTION 2: Use explicit wait for staleness then re-findfrom selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)element = driver.find_element(By.ID, "dynamic")
# Wait until element becomes stale, then find new onewait.until(EC.staleness_of(element))element = wait.until( EC.presence_of_element_located((By.ID, "dynamic")))
# SOLUTION 3: Retry patterndef find_with_retry(driver, locator, max_retries=3): for i in range(max_retries): try: element = driver.find_element(*locator) element.is_displayed() # Verify element is valid return element except StaleElementReferenceException: if i == max_retries - 1: raise return None// ERROR: StaleElementReferenceError// The element was found, but the page refreshed or element was re-rendered
// WRONG - element reference becomes stale after page actionlet button = await driver.findElement(By.id('submit'));await driver.navigate().refresh(); // Page refreshedawait button.click(); // ERROR! Element is stale
// SOLUTION 1: Re-find the element after DOM changeslet button = await driver.findElement(By.id('submit'));await driver.navigate().refresh();button = await driver.findElement(By.id('submit')); // Re-findawait button.click();
// SOLUTION 2: Retry patternasync function findWithRetry(driver, locator, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { try { const element = await driver.findElement(locator); await element.isDisplayed(); // Verify element is valid return element; } catch (e) { if (e.name === 'StaleElementReferenceError' && i < maxRetries - 1) { continue; } throw e; } }}// ERROR: StaleElementReferenceException// The element was found, but the page refreshed or element was re-rendered
// WRONG - element reference becomes stale after page actionIWebElement button = driver.FindElement(By.Id("submit"));driver.Navigate().Refresh(); // Page refreshedbutton.Click(); // ERROR! Element is stale
// SOLUTION 1: Re-find the element after DOM changesIWebElement button = driver.FindElement(By.Id("submit"));driver.Navigate().Refresh();button = driver.FindElement(By.Id("submit")); // Re-findbutton.Click();
// SOLUTION 2: Retry patternpublic IWebElement FindWithRetry(By locator, int maxRetries = 3){ for (int i = 0; i < maxRetries; i++) { try { IWebElement element = driver.FindElement(locator); _ = element.Displayed; // Verify element is valid return element; } catch (StaleElementReferenceException) { if (i == maxRetries - 1) throw; } } return null;}ElementNotInteractableException
Cause: Element exists but cannot be interacted with (hidden, disabled, overlapped).
// ERROR: ElementNotInteractableException// Element is present but not clickable/typeable
// SOLUTION 1: Wait for element to be clickableWebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));WebElement button = wait.until( ExpectedConditions.elementToBeClickable(By.id("submit")));button.click();
// SOLUTION 2: Scroll element into viewWebElement element = driver.findElement(By.id("footer-button"));((JavascriptExecutor) driver).executeScript( "arguments[0].scrollIntoView({block: 'center'});", element);element.click();
// SOLUTION 3: Wait for overlay/modal to disappearwait.until(ExpectedConditions.invisibilityOfElementLocated( By.cssSelector(".loading-overlay")));driver.findElement(By.id("submit")).click();
// SOLUTION 4: Use JavaScript click for stubborn elementsWebElement element = driver.findElement(By.id("hidden-button"));((JavascriptExecutor) driver).executeScript("arguments[0].click();", element);
// SOLUTION 5: Check if element is in a disabled stateWebElement input = driver.findElement(By.id("email"));if (!input.isEnabled()) { // Element is disabled, handle accordingly System.out.println("Element is disabled");}# ERROR: ElementNotInteractableException# Element is present but not clickable/typeable
# SOLUTION 1: Wait for element to be clickablewait = WebDriverWait(driver, 10)button = wait.until( EC.element_to_be_clickable((By.ID, "submit")))button.click()
# SOLUTION 2: Scroll element into viewelement = driver.find_element(By.ID, "footer-button")driver.execute_script( "arguments[0].scrollIntoView({block: 'center'});", element)element.click()
# SOLUTION 3: Wait for overlay/modal to disappearwait.until(EC.invisibility_of_element_located( (By.CSS_SELECTOR, ".loading-overlay")))driver.find_element(By.ID, "submit").click()
# SOLUTION 4: Use JavaScript click for stubborn elementselement = driver.find_element(By.ID, "hidden-button")driver.execute_script("arguments[0].click();", element)
# SOLUTION 5: Check if element is in a disabled stateinput_elem = driver.find_element(By.ID, "email")if not input_elem.is_enabled(): print("Element is disabled")// ERROR: ElementNotInteractableError// Element is present but not clickable/typeable
// SOLUTION 1: Wait for element to be clickableconst button = await driver.wait( until.elementIsEnabled(driver.findElement(By.id('submit'))), 10000);await button.click();
// SOLUTION 2: Scroll element into viewconst element = await driver.findElement(By.id('footer-button'));await driver.executeScript( "arguments[0].scrollIntoView({block: 'center'});", element);await element.click();
// SOLUTION 3: Wait for overlay to disappearawait driver.wait(async () => { const overlays = await driver.findElements(By.css('.loading-overlay')); return overlays.length === 0 || !(await overlays[0].isDisplayed());}, 10000);
// SOLUTION 4: Use JavaScript click for stubborn elementsconst elem = await driver.findElement(By.id('hidden-button'));await driver.executeScript("arguments[0].click();", elem);// ERROR: ElementNotInteractableException// Element is present but not clickable/typeable
// SOLUTION 1: Wait for element to be clickableWebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));IWebElement button = wait.Until( d => { var elem = d.FindElement(By.Id("submit")); return elem.Displayed && elem.Enabled ? elem : null; });button.Click();
// SOLUTION 2: Scroll element into viewIWebElement element = driver.FindElement(By.Id("footer-button"));((IJavaScriptExecutor)driver).ExecuteScript( "arguments[0].scrollIntoView({block: 'center'});", element);element.Click();
// SOLUTION 3: Use JavaScript click for stubborn elementsIWebElement elem = driver.FindElement(By.Id("hidden-button"));((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", elem);TimeoutException
Cause: A wait condition was not met within the timeout period.
// ERROR: TimeoutException// Element didn't appear within the wait time
// SOLUTION 1: Increase timeout for slow pagesWebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(30)); // Longer timeoutWebElement element = wait.until( ExpectedConditions.visibilityOfElementLocated(By.id("slow-element")));
// SOLUTION 2: Add polling interval for dynamic contentWebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));wait.pollingEvery(Duration.ofMillis(500)); // Check every 500mswait.ignoring(NoSuchElementException.class);
// SOLUTION 3: Use custom expected conditionWebElement element = wait.until(driver -> { try { WebElement el = driver.findElement(By.id("dynamic")); return el.isDisplayed() && el.getText().length() > 0 ? el : null; } catch (NoSuchElementException e) { return null; }});
// SOLUTION 4: Check network/AJAX requests completedwait.until(driver -> ((JavascriptExecutor) driver) .executeScript("return document.readyState").equals("complete"));# ERROR: TimeoutException# Element didn't appear within the wait time
# SOLUTION 1: Increase timeout for slow pageswait = WebDriverWait(driver, 30) # Longer timeoutelement = wait.until( EC.visibility_of_element_located((By.ID, "slow-element")))
# SOLUTION 2: Add polling interval for dynamic contentwait = WebDriverWait(driver, 10, poll_frequency=0.5) # Check every 500ms
# SOLUTION 3: Use custom expected conditiondef element_has_text(locator): def _predicate(driver): try: element = driver.find_element(*locator) return element if element.is_displayed() and element.text else None except NoSuchElementException: return None return _predicate
element = wait.until(element_has_text((By.ID, "dynamic")))
# SOLUTION 4: Check network/AJAX requests completedwait.until(lambda d: d.execute_script("return document.readyState") == "complete")// ERROR: TimeoutError// Element didn't appear within the wait time
// SOLUTION 1: Increase timeout for slow pagesconst element = await driver.wait( until.elementLocated(By.id('slow-element')), 30000 // 30 seconds);
// SOLUTION 2: Custom wait conditionconst element = await driver.wait(async () => { try { const el = await driver.findElement(By.id('dynamic')); const text = await el.getText(); return (await el.isDisplayed()) && text.length > 0 ? el : null; } catch (e) { return null; }}, 10000);
// SOLUTION 3: Check network/AJAX requests completedawait driver.wait(async () => { return await driver.executeScript('return document.readyState') === 'complete';}, 10000);// ERROR: WebDriverTimeoutException// Element didn't appear within the wait time
// SOLUTION 1: Increase timeout for slow pagesWebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));IWebElement element = wait.Until( d => d.FindElement(By.Id("slow-element")));
// SOLUTION 2: Custom wait conditionwait.Until(d => { try { var el = d.FindElement(By.Id("dynamic")); return el.Displayed && !string.IsNullOrEmpty(el.Text) ? el : null; } catch (NoSuchElementException) { return null; }});
// SOLUTION 3: Check document ready statewait.Until(d => ((IJavaScriptExecutor)d).ExecuteScript("return document.readyState") .Equals("complete"));WebDriverException: Session Not Created
Cause: Browser/driver version mismatch or browser not installed.
# Check browser versiongoogle-chrome --versionchromedriver --version
# Download matching driver from:# https://chromedriver.chromium.org/downloads# https://github.com/mozilla/geckodriver/releases
# Or use WebDriverManager (Java)# pip install webdriver-manager (Python)// Use WebDriverManager to auto-download correct driverimport io.github.bonigarcia.wdm.WebDriverManager;
// Setup - downloads correct ChromeDriver automaticallyWebDriverManager.chromedriver().setup();WebDriver driver = new ChromeDriver();
// For FirefoxWebDriverManager.firefoxdriver().setup();WebDriver driver = new FirefoxDriver();# Use webdriver-manager to auto-download correct driverfrom selenium import webdriverfrom webdriver_manager.chrome import ChromeDriverManagerfrom selenium.webdriver.chrome.service import Service
# Setup - downloads correct ChromeDriver automaticallyservice = Service(ChromeDriverManager().install())driver = webdriver.Chrome(service=service)
# For Firefoxfrom webdriver_manager.firefox import GeckoDriverManagerservice = Service(GeckoDriverManager().install())driver = webdriver.Firefox(service=service)// In Node.js, use selenium-webdriver's built-in manager// or specify path to manually downloaded driver
const { Builder } = require('selenium-webdriver');const chrome = require('selenium-webdriver/chrome');
// selenium-webdriver 4.x manages drivers automaticallyconst driver = await new Builder() .forBrowser('chrome') .build();// Use WebDriverManager.Net// Install-Package WebDriverManager
using WebDriverManager;using WebDriverManager.DriverConfigs.Impl;
// Setup - downloads correct driver automaticallynew DriverManager().SetUpDriver(new ChromeConfig());IWebDriver driver = new ChromeDriver();
// For Firefoxnew DriverManager().SetUpDriver(new FirefoxConfig());IWebDriver driver = new FirefoxDriver();Quick Reference Table
| Error | Common Cause | Quick Fix |
|---|---|---|
| NoSuchElementException | Element not in DOM | Add explicit wait |
| StaleElementReferenceException | DOM changed after find | Re-find element |
| ElementNotInteractableException | Element hidden/disabled | Wait for clickable, scroll |
| TimeoutException | Wait condition not met | Increase timeout, check locator |
| InvalidSelectorException | Bad CSS/XPath syntax | Validate selector in DevTools |
| NoSuchWindowException | Window was closed | Switch to valid window |
| NoSuchFrameException | Frame doesn’t exist | Verify frame name/id |
| SessionNotCreatedException | Driver/browser mismatch | Update driver version |
Debugging Checklist
- Check locator - Verify in browser DevTools (F12)
- Add wait - Element may need time to load
- Check visibility - Element might be hidden or overlapped
- Check context - Is element in iframe or shadow DOM?
- Check timing - Is there a race condition?
- Check driver version - Does it match browser?
Next Steps
- Debugging Tips - General debugging strategies
- Explicit Waits - Proper wait strategies
- Screenshots and Videos - Capture evidence
Copy-paste recipes for this topic
- Click With a JavaScript Fallback
Try a real click first, then fall back to a JavaScript click only for the specific interception and visibility errors, with a log line so fallbacks are visible.
- Retry on StaleElementReferenceException
Re-find an element and retry the action when the DOM re-renders between locating and using it.