Root Cause Diagnosis
NoSuchWindowException: no such window: target window already closed from unknown error: web view not found means the driver sent a command to a browsing context that no longer exists. When an alert’s accept() or dismiss() triggers window.close() (or the popup hosting the alert closes itself), the driver’s current-window pointer still references the destroyed context. Any following command that needs a live context, such as find_element, title, current_url, or current_window_handle, fails. In fast flows, the same error appears when the window closes between the alert appearing and the next driver call.
Quick Fix
Switch to a surviving window handle immediately after the alert is dismissed. window_handles is safe to call when the current window is gone; current_window_handle is not.
alert = driver.switch_to.alert
alert.accept()
driver.switch_to.window(driver.window_handles[0])
Java equivalent:
driver.switchTo().alert().accept();
driver.switchTo().window(driver.getWindowHandles().iterator().next());
Step-by-Step Resolution
1. Capture window state before triggering the alert
main = driver.current_window_handle
before = set(driver.window_handles)
2. Wait for the alert explicitly
A fixed sleep or a bare switch_to.alert races the page script. Use an explicit wait:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
alert = WebDriverWait(driver, 10).until(EC.alert_is_present())
3. Read everything you need before dismissing
If the accept closes the window, alert properties are unreachable afterward.
text = alert.text
alert.accept()
4. Wait for the window count to settle, then switch
Do not assume the window closed or stayed open; wait for the state you expect.
from selenium.common.exceptions import TimeoutException
try:
WebDriverWait(driver, 3).until(EC.number_of_windows_to_be(len(before) - 1))
except TimeoutException:
pass # window stayed open
remaining = driver.window_handles
driver.switch_to.window(main if main in remaining else remaining[0])
5. Wrap it in one reusable helper
Put this in utils/alerts.py (or your test framework’s helper module):
from selenium.common.exceptions import (
NoSuchWindowException, NoAlertPresentException, TimeoutException,
)
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def accept_alert_safely(driver, timeout=10):
main = driver.current_window_handle
count = len(driver.window_handles)
alert = WebDriverWait(driver, timeout).until(EC.alert_is_present())
text = alert.text
alert.accept()
try:
WebDriverWait(driver, 2).until(EC.number_of_windows_to_be(count - 1))
except TimeoutException:
pass
handles = driver.window_handles
if not handles:
raise RuntimeError("All windows closed after alert; session has no context")
driver.switch_to.window(main if main in handles else handles[0])
return text
6. Optionally let the browser auto-handle prompts
Where the alert content does not matter, set the W3C unhandledPromptBehavior capability so prompts do not interrupt commands. Options are accept, dismiss, accept and notify, dismiss and notify, and ignore. The W3C default is dismiss and notify.
from selenium.webdriver.chrome.options import Options
options = Options()
options.unhandled_prompt_behavior = "accept"
driver = webdriver.Chrome(options=options)
ChromeOptions options = new ChromeOptions();
options.setUnhandledPromptBehaviour(UnexpectedAlertBehaviour.ACCEPT);
WebDriver driver = new ChromeDriver(options);
7. Guard teardown
Calling driver.close() on an already-closed window raises the same exception. Use driver.quit() in fixtures, which ends the session regardless of window state.
@pytest.fixture
def driver():
d = webdriver.Chrome()
yield d
d.quit()
Why This Fails for Some Users
- Tab crash instead of intentional close: Chrome reports the same error when the renderer crashes. In Docker or CI, a small
/dev/shmis the usual cause. Launch with--disable-dev-shm-usageor run the container with--shm-size=2g. Also add--no-sandboxonly when running as root in a container. beforeunloaddialogs: A page with abeforeunloadhandler shows a prompt when the window closes. Chrome only shows it if the page received user interaction, so behavior differs between scripted and manual runs. Dismiss it with the alert API, or setunhandledPromptBehaviortoaccept.- Popup with
window.openerlogic: If the alert lives in awindow.open()popup that closes itself, the main window handle is your only valid target. Store it in step 1; do not rely onwindow_handles[0]if order matters, since handle order is not guaranteed. - Shared driver across threads: Parallel tests using one driver instance can close each other’s windows. WebDriver instances are not thread-safe; use one driver per thread or process.
- Headless mode differences: Legacy
--headlessand--headless=newdiffer in window management and popup handling. If the error appears only headless, test with--headless=newand pin a matching Chrome and ChromeDriver major version. - Driver/browser version mismatch: An outdated ChromeDriver mishandles context destruction. Use Selenium 4.6+ with Selenium Manager, or verify with
chromedriver --versionandgoogle-chrome --version. - Firefox: geckodriver raises
NoSuchWindowException: Browsing context has been discardedfor the same condition. The switch-to-surviving-handle fix applies unchanged. - Selenium Grid or remote drivers: Extra latency widens the race window between alert appearance and the next command. Increase the explicit wait timeout instead of adding
sleepcalls. current_window_handleas a liveness check: It throws when the window is gone. Test liveness withdriver.window_handles(never throws for a missing window) or catchNoSuchWindowExceptionaround the specific call.- Alert triggered inside an iframe: After the window closes, the frame context is also invalid. Call
driver.switch_to.default_content()after switching windows.