Selenium invalid session id (tested)
InvalidSessionIdException: invalid session id means the browser behind your WebDriver session is gone: Chrome crashed or was killed ("session deleted as the browser has closed the connection"), or close() closed its last window. Start a new driver, and fix the cause: memory or /dev/shm in Docker, or code that closes too early.
Setup used in every block
common.py writes a small HTML page to a local file and starts headless Chrome. Exception messages are cut to their first line.
import os, pathlib
from selenium import webdriver
CHROME = os.path.expanduser("~/.cache/ms-playwright/chromium-1248/chrome-linux64/chrome")
def page(html):
p = pathlib.Path("/tmp/sl383/page.html"); p.write_text(html); return p.as_uri()
def driver():
o = webdriver.ChromeOptions()
o.binary_location = CHROME
o.add_argument("--headless=new"); o.add_argument("--no-sandbox"); o.add_argument("--window-size=1000,700")
return webdriver.Chrome(options=o)
1. Reproduce it: the browser died under the session
import os, signal, subprocess
from common import *
d = driver()
d.get(page("<p>hi</p>"))
# simulate a browser crash (out of memory, /dev/shm full in Docker, ...): kill the Chrome process
pid = d.service.process.pid # chromedriver
chrome = subprocess.run(["pgrep", "-P", str(pid)], capture_output=True, text=True).stdout.split()
for p in chrome:
os.kill(int(p), signal.SIGKILL)
for attempt in (1, 2):
try:
d.title
except Exception as e:
print(f"call {attempt}:", type(e).__name__ + ":", e.msg.splitlines()[0])
d.quit()
Output:
call 1: InvalidSessionIdException: invalid session id: session deleted as the browser has closed the connection
call 2: InvalidSessionIdException: invalid session id; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#invalidsessionidexception
Killing Chrome (as the OS does when it runs out of memory) gives exactly the error people search for: the first call says invalid session id: session deleted as the browser has closed the connection, every later call just invalid session id. chromedriver is still running; the browser behind the session is gone, so the only fix is a new driver. Find out why Chrome died: in Docker the usual cause is the 64 MB default /dev/shm (run the container with --shm-size=2g, or add the Chrome argument --disable-dev-shm-usage); otherwise check memory (dmesg for the OOM killer) and very long sessions that accumulate tabs.
2. close() on the last window ends the session
from common import *
d = driver()
d.get(page("<p>hi</p>"))
d.close() # closes the only window
try:
d.title
except Exception as e:
print("after close() of the last window:", type(e).__name__ + ":", e.msg.splitlines()[0])
try:
d.quit()
print("quit() after that: OK")
except Exception as e:
print("quit():", type(e).__name__)
Output:
after close() of the last window: InvalidSessionIdException: invalid session id; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#invalidsessionidexception
quit() after that: OK
driver.close() closes the current window; when it is the only one, chromedriver ends the session, and the next command raises InvalidSessionIdException. Use close() only for extra tabs (then switch_to.window() back to one that is still open), and quit() to finish. Calling quit() afterwards was still fine.
3. After quit(): not InvalidSessionId but MaxRetryError
from common import *
d = driver()
d.get(page("<p>hi</p>"))
d.quit()
try:
d.title
except Exception as e:
print("after quit():", type(e).__module__ + "." + type(e).__name__)
print(str(e).split(" (Caused by")[0])
Output:
after quit(): urllib3.exceptions.MaxRetryError
HTTPConnectionPool(host='localhost', port=42099): Max retries exceeded with url: /session/f0fdee7053df2b89a105408a159aaeca/title
After quit(), chromedriver itself has exited, so the next call does not even get an "invalid session id": the HTTP request to chromedriver's local port is refused, and you get urllib3.exceptions.MaxRetryError ... Max retries exceeded with url: /session/<id>/... caused by Connection refused (only the first line is printed here). Seeing this error means some code still uses a driver after quit(), typically a test fixture that quits in teardown while another test, thread or atexit handler still holds it.
4. Checklist
- One driver per test or per thread; never share one driver between threads.
- Call
quit()exactly once, in afinallyblock or fixture teardown, and do not touch the driver after that. - Docker:
--shm-size=2gor--disable-dev-shm-usage; watch memory. - Recover from a crash by creating a new driver; the old session cannot be revived.
Related: Selenium Unable to obtain driver for chrome, This version of ChromeDriver only supports Chrome version.
Frequently asked questions
What causes invalid session id in Selenium?
The browser for that session no longer exists: it crashed or was killed (often memory or a small /dev/shm in Docker), or driver.close() closed the last window.
Why do I get MaxRetryError Connection refused instead?
The driver was used after quit(): chromedriver has exited, so the HTTP request to its local port is refused. Don't use a driver after quit().
Written with AI assistance. Measured on 2026-10-23 with Selenium 4.51.0 (Python 3.13.5) and headless Chrome for Testing 156.0.8078.4. Each block was run verbatim and the output pasted unedited. PlainHeaders is our extension; Python, Selenium and Chrome are free.