You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
auth: a rolled-back Chrome marker reports as a network problem, and locks the profile out of any GOOGLE_SESSION_ONLY fallback #796
Found during the /gflow:predict audit for #791. Not yet reproduced end-to-end — the chain is read from code, and the last leg is macOS-only. Filed because it changes how #791's fix must be triggered.
The chain
A failed login rolls the Chrome marker back: auth/real_chrome.py:433-434 unlinks .gflow_browser_strategy when not verified and not marker_preexisted. Correct by itself, and deliberately scoped to a first login on a fresh profile.
The next gflow auth status on macOS hits Keychain decryption failure → falls back to the Playwright cookie reader (auth/cookies.py:196).
That reader is marker-gated: cookies.py:139-147 raises SecurityError when channel_for_profile(profile_dir) is not chrome. The marker was just unlinked, so it is not.
SecurityError is not a PermissionError, so it escapes get_chrome_cookie_snapshot's normalization and is flattened to VERIFICATION_ERROR.
The user is told to "check network connectivity" — for a marker-state problem on their own disk, with the network fine.
Why it matters beyond the bad message
On an already-rolled-back profile the outcome is VERIFICATION_ERROR, not GOOGLE_SESSION_ONLY. Any migrated-host fallback keyed only on GOOGLE_SESSION_ONLY — including the one proposed in #793 — therefore never runs on exactly the profiles that have already failed once. This is the argument for widening the trigger to {GOOGLE_SESSION_ONLY, VERIFICATION_ERROR}, or for making the migrated probe a peer oracle rather than a fallback.
It may also explain the inconsistency in #791, where the reporter quotes both outcome=google_session_only and the string "No sign-in detected" (which is NO_SESSION, verification.py:69) — two different profile states across five attempts.
What would settle it
On macOS, on a fresh profile: fail a login once, then run GFLOW_CLI_LOG_LEVEL=DEBUG gflow auth status and check whether the outcome is VERIFICATION_ERROR with a SecurityError underneath. Related: #768 (macOS Keychain modes differ between the real-Chrome login and the Playwright readers) — same OS, adjacent mechanism.
Suggested fix direction
Give SecurityError from the marker gate its own outcome or at minimum its own remediation string — "this profile's browser-strategy marker is missing; re-run gflow auth login --browser chrome" is actionable, "check network connectivity" is not.
Landed: a distinct PROFILE_MARKER_MISSING outcome. The marker gate's SecurityError is no longer flattened into VERIFICATION_ERROR, so the user gets "this profile is missing its Chrome-strategy marker" plus gflow auth login --browser chrome instead of "check network connectivity". Mirrored on the MCP twin as HTTP 409 / retryable: false — neither a network blip (503, retry) nor a dead session (401, re-login) describes a marker that will not reappear on its own.
Two existing tests were updated because they encoded the old classification; one of them turned out to be a near-duplicate that stopped at the marker gate rather than exercising the decryption path its name promised, so it now writes the marker and fails the fallback instead.
Staying open, and why. The chain is still only verified from code and offline tests. Its live trigger is a cookie-store decryption failure, which does not occur on Windows/DPAPI — it is the macOS Keychain case (#768), and there is no Mac here. Per this repo's Iron Law that is a named external blocker, so this is Refs, not Closes.
To close it, someone on macOS needs to: fail a login once on a fresh profile, then run GFLOW_CLI_LOG_LEVEL=DEBUG gflow auth status and confirm the outcome is now profile_marker_missing rather than verification_error.
Adjacent finding, deliberately not fixed here. A synthetic attempt to force the path (a deliberately corrupt cookie store) produced sqlite3.DatabaseError, which is not normalized to PermissionError, so it bypasses the marker gate entirely and still prints "check network connectivity". Same misdirection class, different trigger — a corrupt or locked local file reported as a network fault. Left alone rather than widening the fix's scope.
Reproduced live — and confirmed that #791 is the trigger
This issue was filed as "not yet reproduced end-to-end — the chain is read from code." It is reproduced now, on 2026-09-16, with a Google Workspace account on released 0.76.0. Windows, --browser chrome, real Chrome.
channel_for_profile(profile_flavio.oliva) -> None
profile contents: only .gflow_acl_v1 — the chrome marker is gone
So the rollback at real_chrome.py:433-434 fired exactly as this issue predicted, on a profile the user explicitly created with --browser chrome. Its own comment states the cost: "silently downgrading generation to bundled Chromium."
outcome=google_session_only — labs' NextAuth session is simply never minted for this migrated account. Nothing was unreachable; the endpoint answered, with no session. That is #791, and it makes the rollback fire on every login attempt for an affected account, not as an edge case.
The outcome field added for this issue is what made the distinction legible in the log — it separated "the probe endpoint was unreachable" from "genuinely signed out", and here it says neither: the session is absent while the account is perfectly usable.
Activity
fix(795,796): two auth failures that blame the wrong cause (#797)
ffroliva commentedon Sep 12, 2026
Partially fixed on
developin #797 (4d4ea3df).Landed: a distinct
PROFILE_MARKER_MISSINGoutcome. The marker gate'sSecurityErroris no longer flattened intoVERIFICATION_ERROR, so the user gets "this profile is missing its Chrome-strategy marker" plusgflow auth login --browser chromeinstead of "check network connectivity". Mirrored on the MCP twin as HTTP 409 /retryable: false— neither a network blip (503, retry) nor a dead session (401, re-login) describes a marker that will not reappear on its own.Two existing tests were updated because they encoded the old classification; one of them turned out to be a near-duplicate that stopped at the marker gate rather than exercising the decryption path its name promised, so it now writes the marker and fails the fallback instead.
Staying open, and why. The chain is still only verified from code and offline tests. Its live trigger is a cookie-store decryption failure, which does not occur on Windows/DPAPI — it is the macOS Keychain case (#768), and there is no Mac here. Per this repo's Iron Law that is a named external blocker, so this is
Refs, notCloses.To close it, someone on macOS needs to: fail a login once on a fresh profile, then run
GFLOW_CLI_LOG_LEVEL=DEBUG gflow auth statusand confirm the outcome is nowprofile_marker_missingrather thanverification_error.Adjacent finding, deliberately not fixed here. A synthetic attempt to force the path (a deliberately corrupt cookie store) produced
sqlite3.DatabaseError, which is not normalized toPermissionError, so it bypasses the marker gate entirely and still prints "check network connectivity". Same misdirection class, different trigger — a corrupt or locked local file reported as a network fault. Left alone rather than widening the fix's scope.ffroliva commentedon Sep 16, 2026
Reproduced live — and confirmed that #791 is the trigger
This issue was filed as "not yet reproduced end-to-end — the chain is read from code." It is reproduced now, on 2026-09-16, with a Google Workspace account on released 0.76.0. Windows,
--browser chrome, real Chrome.The chain, measured
gflow auth login --profile flavio.oliva --browser chrome:Immediately afterwards, on disk:
So the rollback at
real_chrome.py:433-434fired exactly as this issue predicted, on a profile the user explicitly created with--browser chrome. Its own comment states the cost: "silently downgrading generation to bundled Chromium."The trigger is #791, not a network problem
outcome=google_session_only— labs' NextAuth session is simply never minted for this migrated account. Nothing was unreachable; the endpoint answered, with no session. That is #791, and it makes the rollback fire on every login attempt for an affected account, not as an edge case.The
outcomefield added for this issue is what made the distinction legible in the log — it separated "the probe endpoint was unreachable" from "genuinely signed out", and here it says neither: the session is absent while the account is perfectly usable.Fixing #791 prevents this entirely
Same profile, same cookies, untouched on disk — only the code differed (#793's migrated-host fallback):
auth_flow_session_unverifiedauth_flow_session_verifiedchannel_for_profileNonechromeThe rollback is gated on
not verified. When verification succeeds it never runs, so this issue does not fire at all.What that means for this issue's scope
Two separable questions, and it is worth deciding which this issue owns:
Should a failed verification roll the marker back at all? The rollback assumes a failure means "this profile is not really a chrome profile". auth: login verification never passes for accounts migrated to flow.google.com (labs NextAuth absent → GOOGLE_SESSION_ONLY forever) #791 shows a failure can also mean "Flow moved hosts and our oracle did not follow" — where the profile is a chrome profile and downgrading it is wrong. A rollback that fires on the wrong premise is worse than none, because it is silent and permanent.
Should it be recoverable? Today the user's only route back is another
gflow auth login, which on an affected account fails the same way and rolls it back again — a loop with no exit until auth: login verification never passes for accounts migrated to flow.google.com (labs NextAuth absent → GOOGLE_SESSION_ONLY forever) #791 is fixed.The macOS leg of the original chain remains unverified; this reproduction is Windows.
chore(release): v0.77.0
fix(auth): name the cookie-file fallback when a re-login repeats; pin…
test(auth): run the real-file #796 tests on Windows; add a portable D…
Merge pull request #1096 from ffroliva/bugfix/796-corrupt-cookie-store
fix(auth): a corrupt cookie store is not a network problem (ffroliva#796