After upgrading a Selenium 3 real-estate listing-filter suite to Selenium 4, every new session fails with an invalid argument error — how do you diagnose and fix it?
answer
- The failure is at session start
- Selenium 4 validates the new-session payload
- Unknown top-level capability keys are refused
- version and platform were renamed
- Browser-only settings live under a prefixed key
basics
~20 sSelenium 4 sends only W3C capabilities, and the remote end rejects any top-level key that is neither a standard capability nor vendor-prefixed. Find the leftover Selenium 3 keys, rename them, and move browser-specific ones into a browser Options object.
solid answer
~50 sSelenium 4 speaks only the W3C WebDriver protocol, so the new-session payload is validated strictly: a top-level capability that is not one of the standard names and does not carry a vendor prefix is rejected, and the client raises `InvalidArgumentException`, often wrapped in a `SessionNotCreatedException`, naming the offending key. Read that key out of the message first — it is nearly always a Selenium 3 leftover. The common ones are renames: `version` became `browserVersion`, `platform` became `platformName`. Anything Chrome-only belongs inside a `ChromeOptions` object, which serialises under the prefixed `goog:chromeOptions` bucket instead of at the top level; `FirefoxOptions` and `EdgeOptions` do the same for their browsers. Keys your own harness invented — a build tag for the listing-filter run, say — must be namespaced or dropped. Fix the shared driver factory once, not each test.
code
java · 17 linesimport java.util.Map;
import org.openqa.selenium.PageLoadStrategy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
public final class ListingFilterDriverFactory {
public static WebDriver create() {
ChromeOptions options = new ChromeOptions();
options.setPageLoadStrategy(PageLoadStrategy.EAGER);
options.setAcceptInsecureCerts(true);
options.addArguments("--window-size=1440,900");
options.setExperimentalOption("prefs", Map.of("intl.accept_languages", "en-GB"));
return new ChromeDriver(options);
}
}go deeper
Be ready to say that Selenium 4 starts a session with W3C capabilities and that an unrecognised key fails the session immediately. Knowing that a browser Options object is where browser settings belong is enough at this level.
An interviewer expects you to explain which capability names are standard, why an extension key needs a vendor prefix and a colon, and how a Selenium 3 capability bag maps onto a Selenium 4 Options object.
Demonstrate the diagnosis, not just the fact: read the refused key out of the exception, trace it to the shared driver factory, and fix the whole suite in one place instead of test by test.
Own how session capabilities are produced across many suites, a typed factory versus per-team property files, and decide what evidence you want to see before an upgrade lands in everyone's pipeline.
## Why an upgraded suite dies at the very first command In **Selenium 4** a browser session begins with a **W3C WebDriver** new-session request, and the remote end validates that request strictly rather than tolerantly. A **capability** — one entry in the map the client sends — is accepted only if its name is one of the standard W3C names, or if it is an **extension capability**, which must be namespaced with a vendor prefix and a colon, such as `goog:chromeOptions`. Anything else is refused outright. Nothing in the **real-estate listing-filter** tests themselves has changed; the keys the driver factory has always sent are simply being checked for the first time. The standard names are a short list, and knowing it is most of the diagnosis: - `browserName`, `browserVersion` and `platformName` — which browser, which version, which platform. - `acceptInsecureCerts`, `pageLoadStrategy`, `proxy` and `timeouts` — session-wide behaviour. - `unhandledPromptBehavior`, `strictFileInteractability` and `setWindowRect` — the remaining standard switches. ## Reading the failure before you change anything 1. Take the exception from the **first** failing test rather than a later one. Every test fails identically here, so the earliest stack trace is the cleanest evidence you have. 2. Find the refused key in the message. Selenium surfaces this as `org.openqa.selenium.InvalidArgumentException`, frequently wrapped in a `SessionNotCreatedException`, and the message names the capability that was rejected. 3. Grep the suite for that key. In a Selenium 3 codebase it is almost always produced by one shared driver factory or one properties file, not by the individual listing-filter tests. 4. Fix it, re-run a single test, and repeat. The payload often carries more than one bad key and the remote end reports the first one it reaches, so the second failure is progress, not a regression. ## The Selenium 3 keys that no longer survive | Selenium 3 spelling | Selenium 4 replacement | How you set it now | |---|---|---| | `version` | `browserVersion` | `ChromeOptions.setBrowserVersion(String)` | | `platform` | `platformName` | `setPlatformName(String)`, with lower-case values such as `linux` | | a top-level `chromeOptions` map | `goog:chromeOptions` | built for you by a `ChromeOptions` object | | a `DesiredCapabilities` bag handed to the driver | a browser `Options` object | `new ChromeDriver(options)` | The first two are pure renames — same meaning, W3C spelling. The last two are the structural half of the migration: browser-specific configuration stops being loose keys and becomes an object. ## Where a browser-only setting goes instead - Chrome command-line switches go to `ChromeOptions.addArguments(...)`, which serialises them into the prefixed `goog:chromeOptions` bucket for you. - Firefox preferences go to `FirefoxOptions.addPreference(...)`, which lands under `moz:firefoxOptions`. - Edge configuration goes to `EdgeOptions`, which lands under `ms:edgeOptions`. - Standard capabilities have typed setters on the Options classes — `setAcceptInsecureCerts(boolean)`, `setPageLoadStrategy(PageLoadStrategy)` — and a typed setter cannot produce a misspelled key. - Only a capability with no typed setter needs `setCapability(String, Object)`. That method is where invalid names come from, so reach for it last and review every use of it during the upgrade. ## The keys your own harness invented A Selenium 3 suite frequently smuggled its own metadata through the capability map — a build label for the nightly listing-filter run, a suite name, an environment tag — because nothing rejected it. In Selenium 4 those keys have two honest destinations: - Namespaced as an extension capability with a prefix containing a colon, if a remote end genuinely consumes them. - Out of the capability map entirely, into your own test context, if nothing on the other side ever read them. This is the usual answer, and deleting them is the smallest change. Note that a correctly prefixed key the remote end does not understand is not guaranteed to be honoured. Prefixing stops the rejection; it does not prove the setting took effect, so verify the behaviour you wanted rather than assuming the key did something. ## Fix it in one place, not test by test The reason old code compiles and then fails at run time is that `DesiredCapabilities` is still a perfectly ordinary capability bag in Selenium 4. The compiler has no opinion about the strings you put in it: ```java DesiredCapabilities caps = new DesiredCapabilities(); caps.setCapability("version", "latest"); caps.setCapability("platform", "WINDOWS"); caps.setCapability("listingFilterBuild", "nightly-42"); ``` All three keys compile and all three are refused at the session request. The replacement is a single factory that every listing-filter test calls, built from typed setters, so the suite has exactly one place where a capability name can be wrong. Three closing cautions. This is **not** a remote-execution problem — the same rejection happens against a driver on your own laptop, so do not start by suspecting infrastructure somebody else owns. It is **not** fixed by pinning the client back to an older release, which only postpones the work. And it is **not** fixed by catching the exception and retrying, because a rejected capability is rejected deterministically on every attempt.
- The message names a capability key nobody on the team recognises. How do you find where it is set?Search beyond the Java sources. Selenium 3 suites commonly merged capabilities from a properties file, an environment variable or a shared harness module, so the key may never appear as a literal in test code. Trace the object the driver factory hands to the constructor and print it once.
- If DesiredCapabilities is the problem, why does the old code still compile?Because `DesiredCapabilities` is still an ordinary mutable capability bag in Selenium 4. The compiler has no opinion about the strings you put in it. The validation moved from build time to the new-session request, which is exactly why the symptom is a green build and a suite that cannot open a browser.
- How do you stop this class of error coming back?Build capabilities in one factory, prefer the typed setters on the Options classes over `setCapability(String, Object)`, and assert the produced capabilities in a unit test. Typed setters cannot misspell a standard name, so the only place a bad key can enter is the one call you are now reviewing.
A Selenium 3 session request was a form a friendly clerk accepted with extra notes scribbled in the margin. Selenium 4 hands the same form to a clerk who returns the whole thing because one field is not on the list.
saying these in an interview costs you the question
- Says Selenium 4 still accepts Selenium 3 capability names and only warns
- Retries or restarts the session instead of reading the rejected key
- Puts Chrome-only switches at the top level instead of the options object
- Assumes pinning an older Selenium version is the fix rather than renaming keys
- Thinks code that compiles proves the capabilities are valid