A Selenium Grid suite stopped getting sessions after browserVersion was pinned in the client's options. Why?
answer
- the request is also a filter
- you asked for something nobody advertises
- more keys means fewer candidate slots
- an exact string, not a range
- send the least the test needs
basics
~20 sEverything the client sends that the Grid matches on narrows the set of slots that may serve it. A pinned version string no node advertises can never match, so the request becomes unroutable and comes back as a session-not-created failure.
solid answer
~50 sAgainst a Grid the options object is a routing key, not just a browser configuration. Selenium 4's Grid compares the request's `browserName`, `browserVersion` and `platformName` against what each node advertises, while extension keys such as `se:name` are carried along rather than matched. A pinned `browserVersion` is a string comparison against the advertised value, not a semantic-version range and not a floor, so pinning a short marketing number against nodes advertising a full build string, or pinning at all after the fleet was rebuilt on a newer image, empties the candidate set. The client then waits and receives a `session not created` error whose message echoes what was asked for. The fix is to ask for the least the test genuinely needs, usually `browserName` alone, and to log the granted capabilities from `getCapabilities()` when you want to know what actually served you.
go deeper
Know that what you put in the options object decides which machines can serve your test, so asking for more is not safer. Start with the browser name and nothing else.
Explain which keys are matched and which are merely carried, and why a version string is compared rather than interpreted as a range of acceptable builds.
Diagnose it from the symptom: a delayed session-not-created failure after a fleet rebuild, traced by comparing the requested capabilities against what the Grid advertises.
Own the standing cost of a pin. It is a capacity commitment written into test code, and it needs an owner on the fleet side or it expires silently.
## The request is also a filter Against a local browser, an options object only describes how the browser should start; anything you add is a preference. Against a Grid the same object is doing a second job: the capabilities in the new-session request are what the Grid uses to **choose a slot**. Every capability you add that participates in matching removes candidate slots. Add enough of them and the set of nodes that can serve you becomes empty — and an empty set is not a slow run, it is a failure. This is why the sentence *"nothing changed except that we pinned the version"* is so often the whole diagnosis. The pin did not change the browser; it changed the population of nodes allowed to answer. ## What the Grid compares, and what it merely carries | capability | part of the match | typical effect on routing | |---|---|---| | `browserName` | yes | the primary filter; nearly always what you want to send | | `browserVersion` | yes | narrows to nodes advertising that version string | | `platformName` | yes | narrows to nodes on that platform | | extension keys such as `se:name` | no | metadata, carried to the node, never a filter | The rule of thumb worth memorising: a key in a vendor namespace — anything containing a colon — is carried through to the session rather than used to pick one. That is exactly why labelling a session never changes where it lands, and why the three unprefixed keys above are the ones that can strand a request. ## Why a version pin is the usual culprit `browserVersion` is a string compared against what a node advertises. It is **not** a semantic-version range and it is not a floor: writing a value does not mean "this version or newer". Three things go wrong with it in practice. - The advertised value is a full build string, and the value you pinned is a shorter marketing number, so the two do not correspond. - Nodes were rebuilt on a newer browser image, and every pinned request in the suite silently became unroutable overnight while nothing in the suite changed. - Only some of the fleet was upgraded, so the pin narrows a twenty-slot Grid to the two slots still on the old build. That request is routable but starved, and it looks intermittent rather than broken — which is the harder version of the same bug. `platformName` has the same shape of problem with a smaller blast radius: pinning it because the local machine happens to be one platform is a habit rather than a requirement. ## What the failure looks like from the client An unroutable request does not fail the way a bad address does. The Grid accepted your request perfectly well; it simply cannot satisfy it. So the client waits, and then receives a **session not created** error whose message echoes the capabilities that were asked for. Two consequences follow for whoever is reading the test report: 1. The delay is a signal, not noise. A failure that arrives after a wait means something answered you; a failure that arrives instantly usually means nothing did. 2. The message is the evidence. It names what was requested, which is exactly what you then compare against what the Grid advertises. How long a Grid holds an unsatisfiable request before giving up, and what it does with it while it waits, are Grid-side settings rather than client concerns. ## Asking for the least you need 1. Start from `browserName` alone and add nothing else until a test genuinely fails without it. 2. If a version really matters, confirm the exact string the Grid advertises for that browser before pinning, and treat the pin as a request for capacity that somebody has to keep supplying. 3. Keep platform out of the request unless the assertion is about the platform. 4. Put labelling and recording under `se:` keys, which cost nothing in routing. 5. Log the **granted** capabilities from `getCapabilities()` on every run, so you know which build actually served the canvas suite without pinning anything to find out. ## When a pin is legitimate Pinning is not a mistake in itself. A canvas suite reproducing a rendering bug in one browser build, or a compatibility check that exists specifically to run on an older engine, has to name what it needs. The discipline is to make the pin deliberate and visible: one clearly named suite that pins, rather than a default that every test inherits, and an understanding with whoever configures the Grid's nodes that a slot for that version will keep existing. A pin is a standing capacity requirement written in your test code, and it fails the day the fleet moves on without you.
- Which capabilities can a client add without narrowing where the session is routed?Keys in a vendor namespace, meaning anything containing a colon. They are carried through to the session rather than used to pick a slot, which is why labelling a session with se:name never changes where it lands. The unprefixed browser, version and platform keys are the ones that filter.
- The Grid does have nodes on the pinned version, yet sessions still fail after a long wait. What now?The request is routable but starved: the matching slots exist and are all busy. From the client the symptom is identical to no matching slot at all, so the distinction has to come from the Grid's own view of its slots and waiting requests, not from the exception. A pin that leaves you two slots out of twenty produces exactly this.
saying these in an interview costs you the question
- Assumes a short browserVersion is treated as a range matching newer builds
- Blames the network when the Grid answered and refused the request
- Pins platformName and browserVersion by habit on every request
- Thinks adding capabilities makes the Grid try harder to find a node
- Expects an unmatched request to fail instantly like a bad address