Selenium TimeoutException: Message: (tested)
selenium.common.exceptions.TimeoutException: Message: with nothing after it means a WebDriverWait condition never became true; the message is empty unless you pass message= to until(). Usually the locator is wrong, the element is in an iframe, or you waited for visibility of a hidden element.
Setup used in every block
common.py writes a small HTML page to a local file and starts headless Chrome.
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: "TimeoutException: Message:" with nothing after it
from common import *
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
d = driver()
d.get(page('<input id="q">'))
try:
WebDriverWait(d, 2).until(EC.presence_of_element_located((By.ID, "#q")))
except TimeoutException as e:
print(repr(str(e).splitlines()[0]), "+", len(str(e).splitlines()) - 1, "stacktrace lines")
try:
WebDriverWait(d, 2).until(EC.presence_of_element_located((By.ID, "#q")),
message='no element with id "#q" after 2s')
except TimeoutException as e:
print(repr(str(e).splitlines()[0]), "+", len(str(e).splitlines()) - 1, "stacktrace lines")
print("By.ID 'q':", WebDriverWait(d, 2).until(EC.presence_of_element_located((By.ID, "q"))).tag_name)
print("By.CSS_SELECTOR '#q':", WebDriverWait(d, 2).until(EC.presence_of_element_located((By.CSS_SELECTOR, "#q"))).tag_name)
d.quit()
Output:
'Message: ' + 20 stacktrace lines
'Message: no element with id "#q" after 2s' + 20 stacktrace lines
By.ID 'q': input
By.CSS_SELECTOR '#q': input
WebDriverWait(...).until() raises TimeoutException when its condition never became true within the timeout. By default the message is empty, which is why the error reads just Message: followed by a stacktrace (from chromedriver, not your code). Pass message= to until() so your logs say what you were waiting for.
The cause in this block is the most common one: a wrong locator. By.ID takes the bare id ("q"); "#q" is CSS syntax and only works with By.CSS_SELECTOR. Before raising the timeout, check the locator with len(driver.find_elements(by, value)) on the loaded page.
2. The element is there, but the condition cannot become true
from common import *
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
d = driver()
d.get(page('<iframe srcdoc="<button id=go>Go</button>"></iframe><p id="msg" style="display:none">saved</p>'))
for name, cond in [("presence of #go (inside iframe)", EC.presence_of_element_located((By.ID, "go"))),
("visibility of #msg (hidden)", EC.visibility_of_element_located((By.ID, "msg"))),
("presence of #msg (hidden)", EC.presence_of_element_located((By.ID, "msg")))]:
try:
WebDriverWait(d, 2).until(cond)
print(name, "-> OK")
except TimeoutException:
print(name, "-> TimeoutException")
WebDriverWait(d, 2).until(EC.frame_to_be_available_and_switch_to_it((By.TAG_NAME, "iframe")))
print("after switching into the frame:", WebDriverWait(d, 2).until(EC.element_to_be_clickable((By.ID, "go"))).text)
d.quit()
Output:
presence of #go (inside iframe) -> TimeoutException
visibility of #msg (hidden) -> TimeoutException
presence of #msg (hidden) -> OK
after switching into the frame: Go
Two other frequent causes: the element is inside an <iframe> (the wait searches only the current frame, so switch with EC.frame_to_be_available_and_switch_to_it first), and the wrong condition: visibility_of_element_located times out for an element that exists but is hidden, while presence_of_element_located succeeds for it. Pick the condition that matches what you need next: presence to read it, visibility to read visible text, element_to_be_clickable to click.
3. TimeoutException from driver.get(): page load timeout
import threading, time
from http.server import ThreadingHTTPServer, BaseHTTPRequestHandler
from common import driver
from selenium.common.exceptions import TimeoutException
class Slow(BaseHTTPRequestHandler):
def do_GET(self):
time.sleep(5)
self.send_response(200); self.end_headers(); self.wfile.write(b"<p>slow</p>")
def log_message(self, *a): pass
srv = ThreadingHTTPServer(("127.0.0.1", 8963), Slow)
threading.Thread(target=srv.serve_forever, daemon=True).start()
d = driver()
d.set_page_load_timeout(2)
t = time.time()
try:
d.get("http://127.0.0.1:8963/")
except TimeoutException as e:
print(f"after {time.time() - t:.1f}s:", type(e).__name__ + ":", e.msg.splitlines()[0])
d.quit(); srv.shutdown()
Output:
after 2.0s: TimeoutException: timeout: Timed out receiving message from renderer: -0.002
A different TimeoutException comes from driver.get() itself when the page takes longer than set_page_load_timeout() (the default is 300 seconds). Chromedriver words it as timeout: Timed out receiving message from renderer. Raise the timeout, or, if you only need the DOM and not every image and script, use options.page_load_strategy = "eager", which returns at DOMContentLoaded.
4. Checklist
- Add
message=to everyuntil(). - Check the locator with
find_elements:By.IDtakes no#,By.CLASS_NAMEtakes one class, no dots or spaces. - Inside an iframe? Switch to it first.
- Use the weakest condition you need (presence < visibility < clickable).
- Headless runs can render a different (mobile) layout: set
--window-size.
Related: Selenium element not interactable, Selenium element click intercepted, Selenium StaleElementReferenceException.
Frequently asked questions
Why is the Selenium TimeoutException message empty?
WebDriverWait.until() raises TimeoutException with the message you pass to until(message=...); without one it is empty, so only 'Message:' and a stacktrace are printed.
Why does WebDriverWait time out when the element exists?
Common reasons: the locator is wrong (e.g. By.ID with '#id'), the element is inside an iframe you have not switched to, or you wait for visibility of an element that is hidden.
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.