File Uploads, Downloads, Cookies, Storage, and Session State: Diagnostics, Failure Modes, and Production Practices
Diagnose browser-state failures by preserving the first evidence and identifying the owner boundary. The objective is not “make the file appear” but explain whether the runner, browser, AUT origin, profile, Grid node, or CI artifact layer owns the failure.
Learning objectives
- Diagnose upload paths unavailable on a remote node and download files written outside the intended workspace.
- Detect stale download artifacts before they can create false passes.
- Interpret invalid cookie-domain failures and state leakage between tests.
- Recognize privacy/security risks in profiles, downloads, screenshots, and logs.
- Apply the chapter diagnostic sequence without blanket retries, broad deletion, or browser restarts.
- Repair one intentionally broken cookie/download example while preserving original evidence.
1. Failure taxonomy by owner
The following table organizes the key choices and evidence for Failure taxonomy by owner. Use it together with the surrounding prose so the rows serve as a comparison aid rather than standalone rules.
| Symptom | Likely owner boundary | First evidence |
|---|---|---|
| file input rejects/path not found on remote run | runner ↔ Grid node transfer | runner file existence, driver type/file detector, remote exception |
| download “missing” but browser showed success | browser download manager/path/CI artifact collection | configured directory, browser prefs/capabilities, directory listing |
| download test passes before click | test filesystem contamination | directory listing + timestamps/hashes before action |
| InvalidCookieDomainException | cookie scope/current URL | current_url + cookie domain requested |
| next test starts authenticated | shared profile/cookie/storage/account state | session/profile identity + cookie/storage keys before test |
| artifact contains secrets/PII | evidence retention/profile/download boundary | artifact manifest and redacted metadata—not secret contents in logs |
2. Diagnostic sequence
- Preserve first-failure evidence: exception class/message, current URL, session/browser versions, path names (redacted if sensitive), directory manifest, cookie/storage key names.
- Confirm versions: Selenium binding, browser, driver/Grid.
- Confirm target/environment/test data: exact loopback/CI origin and generated-file provenance.
- Inspect session/capabilities/context: local vs RemoteWebDriver, download capability/preferences, current URL/window.
- Inspect element/state: file input type, selected filename/application result, cookie/storage scope.
- Inspect AUT/network/browser evidence: did the application expose the download; did server-side state change?
- Remote only: inspect Grid/node/queue and artifact-transfer boundary.
- Apply least destructive correction and rerun the smallest scenario.
3. Intentionally broken example: wrong-domain cookie
The following example makes the Intentionally broken example: wrong-domain cookie behavior concrete. Read it with the stated assumptions, then compare its observable output or state changes with the explanation that follows.
from selenium import webdriver
from selenium.common.exceptions import InvalidCookieDomainException
URL = "http://127.0.0.1:8776/"
driver = webdriver.Chrome()
try:
driver.get(URL)
try:
driver.add_cookie({
"name": "academy_mode",
"value": "synthetic",
"domain": "example.invalid",
})
except InvalidCookieDomainException as exc:
print("FIRST_FAILURE", type(exc).__name__)
print("current_url", driver.current_url)
print("requested_domain", "example.invalid")
print("existing_cookie_names", [c["name"] for c in driver.get_cookies()])
raise
finally:
driver.quit()
The exception is meaningful: the test tried to set a cookie outside the current browsing context's domain. Do not work around it by disabling security or changing DNS. Repair the test contract.
4. Least-destructive repair
The following example makes the Least-destructive repair behavior concrete. Read it with the stated assumptions, then compare its observable output or state changes with the explanation that follows.
driver.get("http://127.0.0.1:8776/")
# Host-only cookie: let the current origin define the host scope.
driver.add_cookie({"name": "academy_mode", "value": "synthetic", "sameSite": "Lax"})
cookie = driver.get_cookie("academy_mode")
assert cookie is not None
assert cookie["value"] == "synthetic"
If your business case truly requires a parent-domain cookie, navigate to a compatible host and assert the exact domain/path contract instead of copying a generic snippet.
5. Stale download false positive
A classic anti-pattern is:
The following example makes the Stale download false positive behavior concrete. Read it with the stated assumptions, then compare its observable output or state changes with the explanation that follows.
# BROKEN DESIGN: shared path may contain yesterday's file.
downloaded = Path.home() / "Downloads" / "report.csv"
driver.find_element(By.ID, "download").click()
assert downloaded.exists()
This assertion can pass even if the current click did nothing. The repair is architectural: create a new test-owned directory before session creation, assert it starts empty, use a deterministic expected filename/content, and retain before/after manifests.
6. Upload path unavailable on a remote node
If a RemoteWebDriver run reports a bad path, prove the runner file
exists first. Then inspect the RemoteWebDriver/file detector rather
than mounting random host directories into Grid. Python's current
RemoteWebDriver defaults to LocalFileDetector, which is
designed to recognize local file inputs and transfer them to the
remote end.
from pathlib import Path
from selenium import webdriver
source = Path("synthetic.txt").resolve()
assert source.is_file(), source
options = webdriver.ChromeOptions()
driver = webdriver.Remote("http://127.0.0.1:4444", options=options)
try:
print("driver_type", type(driver).__name__)
print("file_detector", type(driver.file_detector).__name__)
# Only after this evidence should the test send source to input[type=file].
finally:
driver.quit()
7. Session leakage between tests
If test B begins authenticated, do not immediately delete cookies and rerun. Capture the initial cookie names, storage keys, profile path policy, session ID, and test-account identity. A reused profile can retain more than cookies; a reused server-side account can also retain state even with a fresh browser.
8. Privacy and secrets
Do not upload real credentials, SSH keys, customer exports, or browser profile databases to “test” file handling. Avoid archiving entire profile directories. Prefer evidence such as filename, byte size, cryptographic hash, sanitized MIME type, and synthetic content identifiers. Download retention should follow the same least-data rule as CI logs.
9. Troubleshooting shortcuts to reject
- Blanket retry: can turn state leakage into nondeterministic passes.
- Giant timeout: cannot repair wrong filesystem ownership or cookie scope.
- Browser/Grid restart: destroys evidence and may mask persistent setup defects.
- TLS disablement: unrelated to local file/path or cookie-domain diagnosis.
- Wildcard cleanup of shared directories: can delete unrelated files and still fail to prove test isolation.
- Personal profile reuse: imports uncontrolled secrets and state.
10. Performance only where causal
Separate browser startup/profile creation, upload transfer time, AUT processing, browser download time, remote artifact transfer, and evidence hashing. A slow 100 MB Grid upload is not the same problem as a slow browser click. Keep Chapter 11 fixtures tiny so timing diagnoses architecture rather than bandwidth volume.
11. Summary and next step
File/state diagnosis begins with ownership. Preserve first evidence, prove the current origin/session/path, then correct the smallest boundary. Lesson 5 packages those habits into a teardown-focused checkpoint.
Knowledge check
What does InvalidCookieDomainException tell
you?
The requested cookie domain does not match a domain allowed by the current browsing context; inspect current URL and intended cookie scope.
Why is checking only report.csv.exists() unsafe in
a shared Downloads folder?
A stale file can satisfy the assertion before the current download succeeds.
What should you inspect first when a remote upload path fails?
Prove the runner file exists, confirm RemoteWebDriver/file detector state, and identify the runner-to-node transfer boundary.
Why can deleting cookies fail to restore isolation?
Profiles can retain localStorage, cache, service-worker or other browser state, and the server-side test account may also retain state.
Why should first-failure artifacts avoid full profile copies?
Profiles may contain credentials, tokens, history, PII, and unrelated state. Prefer minimal sanitized evidence.
Official references and version notes
- Selenium 4.47 release notes — stable baseline pinned for this chapter.
- Selenium downloads — current stable bindings and Selenium Server/Grid versions.
- File upload — use a file input and send the full path; do not automate the OS chooser.
- Working with cookies — WebDriver cookie create/read/delete semantics.
- Python RemoteWebDriver API — LocalFileDetector default plus remote downloadable-file methods.
-
Python common Options API
—
enable_downloadscapability surface. - File downloads guidance — browser-triggered downloads do not provide portable progress semantics; prefer lower-layer verification where appropriate.
- Selenium API deprecations — Web Storage — local/session storage are not W3C WebDriver commands; use page-context script when storage inspection is required.
-
Python exceptions
— includes
InvalidCookieDomainException.
Version-sensitive behavior was rechecked against current primary
documentation on 2026-08-28. Mandatory examples pin Selenium
Python 4.47.0, require Python 3.10+, use a supported locally
installed Chromium-family browser with Selenium Manager for driver
resolution, and target only 127.0.0.1. Chromium
download preferences are intentionally labeled browser-specific.
Remote/Grid file-transfer and downloadable-file APIs are optional
extensions to the local path. JavaScript execution appears only
for Web Storage access, where Selenium explicitly notes
local/session storage are not W3C WebDriver commands. UI
interactions remain native WebDriver interactions.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.