The automation’s results made no sense — a form half-filled with data it never entered, dropdowns snapping shut mid-selection. Nothing was broken. Two of us were driving the same tab.
A shared-surface collision is a class of fault where two independent actors operate on one mutable interface, so each one’s actions disrupt state the other is relying on.
Table of Contents
The symptom: results that make no sense
The tell is incoherence, not error. The automation reports doing one thing while the page shows another. A form carries values the script never typed. A selection the script just made is gone a moment later. A dropdown the script opened is closed before it can pick from it. Individually each event looks like a flaky selector or a timing bug; together they refuse to form a consistent story.
That incoherence is the signature. A genuine bug in the automation fails the same way each run. This fails differently each run, because the failure is not in the automation — it is in the collision between the automation and something else touching the same page.
A bug repeats. A collision improvises.
Step 1 — “The automation has a timing bug”
The first hypothesis is always internal: the script is racing the page, a selector is flaky, a wait is too short. It is worth checking because it is common and cheap to rule out.
Here it did not hold. The waits were adequate and the selectors were sound; the same step that failed one moment worked the next with no code change. A timing bug inside the automation does not spontaneously fix itself between two identical runs. Something outside the script was changing the ground under it.
Step 2 — “The page is unstable”
The second guess is that the page itself re-renders unpredictably — an async load rewriting the DOM, a framework redrawing under the script. Also plausible, also worth eliminating.
But the disruptions did not match the page’s own rhythm. Fields were being filled, not just re-rendered; selections were being cleared as if by a click, not by a redraw. These were not the page acting on itself — they had the fingerprints of a second operator: half-typed text in a field the script had not reached, a stray navigation the script did not issue.
Re-renders change how a page looks; a second driver changes what it contains.
Step 3 — Two operators, one tab
The realization is uncomfortable because the second operator was us — a person working by hand in the very tab the automation was driving. The automation would navigate the tab to start its task, wiping the form the person had half-filled. The person would click into a field, collapsing a dropdown the automation had just opened. Each was doing exactly the right thing on the assumption that it was the only one there.
On one shared, mutable surface, that assumption is false, and nothing about the surface enforces it. A browser tab has no notion of “whose turn it is.” Both actors have full control at all times, so their actions interleave arbitrarily, and the result is the incoherent, unreproducible mess of the symptom. The bug was never in either party — it was in the sharing.
The fix: give the automation its own tab
The resolution is isolation, and it is structural rather than clever. The automation claims a tab of its own and works only there; the human’s tabs are left alone.
The reliable way to make that stick is for the script to tag its tab — mark it with an identifier when it creates it, and on every later run look for the tab bearing that tag rather than grabbing whatever tab is frontmost. That way the automation reconnects to its own workspace across runs and never wanders into a tab a person is using.
- On startup, find the tagged tab; if absent, create one and tag it. The automation always works in that tab and no other.
- Never operate on the active/frontmost tab by default. “Whatever is in front” is whatever the human is using — the exact tab to avoid.
- Leave every other tab to the person. Isolation only holds if the automation is disciplined about staying in its lane.
Applied, the incoherent failures vanish, because the interleaving that caused them cannot happen: there are no longer two drivers on one wheel.
What isolation does and does not solve
A dedicated tab removes collisions over the page; it does not isolate everything two actors might share. A logged-in session, cookies, and server-side state are still common to both — if the human logs out in their tab, the automation’s tab loses the session too, and if both act on the same account server-side, they can still conflict there. Isolation at the tab level is the fix for the shared-DOM collision specifically, which is the one that produces the erratic half-filled-form symptom; broader shared state needs its own boundaries (a separate session or account for the automation where that matters). And the tag only helps if the script actually honors it — the discipline of never touching the frontmost tab is part of the fix, not an optional nicety — the same operational care as knowing which process a “stop” actually kills.
The short version
When an automated browser session and a person both act in the same tab, they corrupt each other’s work: the script wipes the form the human is filling, the human closes the dropdown the script is using, each reads state the other just changed. The symptoms are erratic and unreproducible because they depend on the arbitrary interleaving of two actors on one mutable surface — which is why it reads as a timing bug or an unstable page before you realize it is a second driver. The fix is isolation: the automation creates and tags its own tab, always reconnects to that tagged tab, and never operates on the frontmost one, leaving every other tab to the human. It resolves the shared-DOM collision; shared session and account state still need their own boundaries.
Frequently Asked Questions
Why does a script behave erratically when I’m also using the browser?
Because you are both acting on the same page, and neither of you can see the other’s actions coming. The script navigates or types and disrupts what you were doing; you click or scroll and disrupt what it was doing. The interleaving is different every run, so the failures look random. It is not a bug in the script — it is a collision between two independent drivers on one shared surface.
How is this different from a normal timing or race-condition bug?
A timing bug inside the automation fails the same way on identical runs, because the race is between the script and the page. A shared-tab collision fails differently each run, because the race is between the script and a human whose actions are not reproducible. The tell is incoherence: the same step works then fails with no code change, and the page shows state the script never produced.
How do I stop an automation from interfering with my browsing?
Give it its own tab. Have the script create a dedicated tab, tag it with an identifier, and on every run reconnect to the tab bearing that tag instead of using whatever tab is in front. Then it works only in its own workspace and leaves your tabs untouched. The key discipline is never defaulting to the active tab, because that is the one you are using.
Why shouldn’t automation just use the currently active tab?
Because the active tab is, by definition, the one a person is most likely using right now. Defaulting to it puts the automation directly in the human’s workspace, guaranteeing collisions the moment both act. A dedicated, tagged tab that the script owns removes the overlap entirely; the active tab should be treated as off-limits precisely because it is where the human attention is.
Does a dedicated tab fully isolate the automation from me?
It isolates the page, which fixes the erratic shared-DOM collisions, but not everything. A logged-in session, cookies, and server-side account state are still shared between your tab and the automation’s — log out in yours and its session drops too; act on the same account and you can still conflict server-side. For those, the automation needs its own session or account boundary; the dedicated tab solves the DOM-level problem specifically.
How does tagging the tab help across multiple runs?
A tag is an identifier the script writes onto its tab when it creates it, so on a later run it can search for the tab carrying that tag and reconnect to the same workspace instead of opening a new one or grabbing a random tab. Without the tag, a script that just uses “the current tab” drifts into whatever is in front; with it, the automation reliably returns to its own lane every time.