A sticky session that has expired does not announce itself. In the browser it looks like pages failing to connect, with net::ERR_TUNNEL_CONNECTION_FAILED and net::ERR_ABORTED. In a proxy check run a minute later it looks like a perfectly healthy proxy, somewhere else. We lost most of a measurement run before we read those two together as one event: the session's lifetime had run out and the gateway had moved us.

The run where it happened

The proxy was a residential gateway with a sticky session spelt into the username, in the form -session-<hex>-lifetime-60. That asks the seller to hold one exit for sixty minutes. For the first hour it did, from Mililani Town, Hawaii.

We were running a subset of the detection catalogue through one profile, one site after another. Four rows came back unreachable. One row next to them loaded fine. Read row by row, that looks like four third-party sites having a bad afternoon, and the one that worked makes it look like flaky sites rather than a flaky exit.

Then we checked the proxy. It answered, the tunnel opened, the check passed. The exit was now in Walnut Ridge, Arkansas.

Put side by side, this is what each side reported:

WhereWhat it said
the browsernet::ERR_TUNNEL_CONNECTION_FAILED, net::ERR_ABORTED
the proxy checkok, tunnel ok, and a different city

Neither line contains the word expired. The browser was still sending the old token and the gateway was refusing it, so connections failed. A new connection from the checker got a new exit, so the proxy looked fine. Both reports were true, and between them they hid the cause.

Paste one gateway line. Every profile mints its own exitIn Mosaic: Provider minting. One gateway line, a separate exit for every profile. Free holds 3 profiles. Pro is $49 a month for any number.

How it works: Provider minting

Why a sticky session expired proxy looks healthy

A session id in the username is a request, not a reservation you hold. The gateway keeps a mapping from that id to an exit for as long as the lifetime says, or for as long as that exit stays up, and after that the mapping is gone. What happens to traffic still carrying the old id is up to the seller. In our run there was a stretch of refusals, then a new exit.

A proxy checker opens a fresh connection, asks where it came out and whether a TLS tunnel works. A freshly assigned exit passes all of that. So the check is honest about the proxy as it is now and silent about whether it is the proxy you had an hour ago. The only clue is the location, and only if you remember the old one.

For a profile, the location is not a detail. Mosaic draws a profile's timezone, language and geolocation from its proxy's measured exit, so a profile set up for an exit in Hawaii carries Hawaii's clock. An exit that has moved to Arkansas behind it is a profile whose timezone and IP disagree, which is the first comparison a consistency scanner makes.

What to do when unreachable rows come in a cluster

Two habits came out of this run, and both are cheap.

First, treat failures that arrive together as one failure. Three unrelated sites do not go down in the same minute, and the thing they share is the exit. Re-check the proxy before you investigate any site, and compare the city it reports with the city it reported before.

Second, size the session to the work. A run that lasts longer than the session lifetime is not one experiment, because the exit underneath it changes halfway through. Before a long run, mint a fresh session token and give it a lifetime that covers the run, rather than starting at minute fifty of an old one.

What Mosaic does about it

Mosaic checks a profile's proxy before every launch, and a profile does not open behind a proxy that has not answered and tunnelled. That catches a dead session at the door. It cannot catch one that dies an hour into a browser that is already open, which is what happened here.

When a launch finds a session that reaches nothing, a session Mosaic minted from a provider costs a different session rather than three more tries at the same dead token, because a dead residential session stays dead for every retry on it. A session you pinned yourself is never moved; the launch is refused and says why. A different kind of rotation, a fresh exit on every launch, once failed in its own way, saved and then ignored by three launches, which is in the setting was saved, and three launches ignored it. The case where a session token is refused outright, on a port that rotates every connection, is in a session token on a rotating port.

And when the detection tests come back with a block of unreachable rows, we now read that as a proxy symptom first. Why a profile's timezone and language have to match its exit is part of how to manage multiple accounts without getting them linked.