Repository navigation
[Bug]: T3 Connect reports "Your cloud sign-in changed" when the host is just overloaded #11004
Description
Activity
Triage
Confirmed on current
main. This is a real client-runtime bug: a pending or slow-to-activate cloud session is reported as an account switch.What the code does
sessionChanged()inpackages/client-runtime/src/authorization/service.tsis aConnectionBlockedErrorwith Your cloud sign-in changed. Sign in again to authorize the environment.assertSessionandgetDpopTokenraise it whenevercloudSession.identityisNone, or is a different object than the identity captured when the attempt started.On web and mobile, that identity is the
managedRelaySessionAtomvalue. The atom staysnulluntilManagedRelayAuthProvider/CloudAuthProviderfinishes Clerk load and theactivateAfterTransitionpromise chain.CloudSessionhas no pending state —Nonemeans both “not ready yet” and “signed out / switched.”The supervisor parks on blocked errors. When activation finally lands,
managedRelayAccountChangesretries andconnectionStatusTextcarries the stale reason into Failed to connect. Reconnecting... Reason: …. That matches the report, including recovery once load drops.setManagedRelaySessionalready keeps the session object stable across same-account token refreshes (CloudSessionIdentityis documented as stable for one signed-in session). Object-ref compare is intentional for that contract. The hole is treatingNoneas “changed.”The 3s
CACHED_ENDPOINT_SOCKET_TIMEOUT_MSon the cached websocket-ticket path (vs 10s for other remote calls) is a likely amplifier: a slow-but-valid ticket fails transiently,authorizeDpopdiscards the cached access token, re-bootstraps, and can hit theNonewindow again.This logic landed in #9594. Existing tests correctly treat logout during renewal as blocked; they do not cover authorize while identity is still
Nonebecause activation has not finished.Not a duplicate of #5031
#5031 is the same reconnect chrome on a different failure (
GET /ws→ 204 on a nightly relay). Leave both open.Suggested fix
- Separate “session not available yet” from “session changed.”
Nonewith no captured identity and no account-switch evidence should be aConnectionTransientError(or a dedicated pending state onCloudSession), notsessionChanged(). - Keep
sessionChanged()for a captured identity whoseaccountIddiffers, and for logout mid-renewal. - Consider not discarding a cached access token when the cached-endpoint ticket times out, and/or scaling that 3s cap under load.
Do not make every
Nonetransient — a real sign-out should still block with a sign-in message (clerkTokenalready has Sign in to T3 Connect…).No open PR for this. Accepting as a minor, self-recovering bug with a misleading diagnosis.
- Separate “session not available yet” from “session changed.”
- addedbugSomething is broken or behaving incorrectly.Something is broken or behaving incorrectly.acceptedfeature request acceptedfeature request acceptedvia-triageFiled through npx t3 triageFiled through npx t3 triage
on Sep 9, 2026 - added a commit that references this issue
on Sep 23, 2026 - added 3 commits that reference this issue
on Oct 1, 2026 Confirming the triage from a mobile angle and adding a repro without host overload.
Device: Samsung Galaxy A55. App: self built APK from current main, Play Store version uninstalled first. Exact commit on request.
I see the same string from this issue:
Failed to connect. Reconnecting... Reason: Your cloud sign-in changed. Sign in again to authorize the environment.
My sign in did not change. The account screen still shows me as signed in and the environments stay in the list. It is only a connection error, no deleted environments.
Repro without reboot:
- Open the app once so sessions exist.
- Minimize the app with the Home gesture. Do not swipe it away in Recents, only send it to background.
- Turn airplane mode on.
- Force stop the app via Android Settings.
- Turn airplane mode off.
- Open the app again. The error appears.
Counter tests:
Normal reboot, wait until the phone is idle and WiFi is stable, then open the app: works. Forced reboot with Power plus Volume Down, same waiting: works. So the trigger looks like a cold start while network or Clerk activation is not ready yet, not reboot corruption.
Healing note for the airplane mode case only: the error does not heal while the app stays open with network back. Full close and reopen heals it, then the retry has a present session and connects.
This matches the None identity window described here.
- added a commit that references this issue
on Oct 9, 2026
Before submitting
Area
apps/web
(The failing logic is in
packages/client-runtime, which the dropdown does not list. The message is surfaced by the web client, and the timing that triggers it comes fromapps/web/src/cloud/managedAuth.tsx.)Steps to reproduce
Expected behavior
While the machine is overloaded the client should report a transient condition, something along the lines of "Reconnecting, the environment is slow to respond", or a timeout, and keep retrying. The sign-in is still valid and nothing about it changed.
Actual behavior
The connection status reads:
The sign-in did not change. Signing out and back in does nothing, because there is nothing wrong with the session. The connection recovers on its own once load drops, which is the tell that the message is describing the wrong cause. The practical cost is that the message sends you to fix an auth problem that does not exist instead of the load problem that does.
Impact
Minor bug or occasional failure (misleading diagnosis, self-recovering)
Version or commit
0.0.40. The string is present in the shipped bundle for that release, and the code below was read at
main@de37964db, whosepackage.jsonis also 0.0.40.Environment
Low-power arm64 single-board Linux host, recent Node. Client is the T3 Code web app, connecting through T3 Connect. Nothing here looks hardware specific: any host slow enough to delay Clerk load or the activation promise chain should reproduce it.
Logs or stack traces
Failed to connect. Reconnecting... Reason: Your cloud sign-in changed. Sign in again to authorize the environment.No stack trace: this is a handled
ConnectionBlockedErrorrendered into the connection status line, not a throw.Screenshots, recordings, or supporting files
None. The full text of the status line is quoted above.
Workaround
Wait for the load to drop. The connection recovers without any sign-in action.
Diagnosis
The message comes from
sessionChanged()inpackages/client-runtime/src/authorization/service.ts:224:It is raised by
assertSessionand bygetDpopTokenwhenevercloudSession.identityisNone, or is a different object reference than the identity captured when the attempt started. On web,identityis themanagedRelaySessionAtomvalue (apps/web/src/connection/platform.ts:185), and that atom isnulluntilManagedRelayAuthProvideractivates it.Two things make "identity is not available yet" indistinguishable from "the user signed in as somebody else":
ManagedRelayAuthProvider(apps/web/src/cloud/managedAuth.tsx) bails out while!isLoaded(line 51), and even on the signed-in path it defersactivateManagedRelayAuthenticationbehind a promise chain (activateAfterTransition, line 92). On a loaded machine, Clerk taking longer to load and that promise chain taking longer to drain both widen the window where the atom is stillnullwhile the connection supervisor is already attempting. Every attempt in that window fails withsessionChanged().identityis compared by reference (current.value !== identity). Anything that replaces the session object rather than updating it in place reads as an account change.setManagedRelaySessiondeliberately keeps the object stable across same-account token refreshes, so this is handled for the common case, but theNonecase has no such guard and produces the same message.Because
sessionChanged()is aConnectionBlockedError, the supervisor moves toblockedand parks. When activation finally lands,managedRelayAccountChangesfires the credentials-changed signal and the supervisor retries, carrying the stale failure into the nextconnectingstate aslastFailure. That is exactly the "Failed to connect. Reconnecting... Reason: ..." shape fromconnectionStatusTextinpackages/client-runtime/src/connection/presentation.ts:68, and it explains why the message is shown while the client is in fact recovering.Likely making it worse on a slow host:
CACHED_ENDPOINT_SOCKET_TIMEOUT_MSis 3000 ms (service.ts:82). On an overloaded host the/api/auth/websocket-ticketround trip against a cached endpoint routinely exceeds that, soauthorizeDpopdiscards a perfectly good access token, re-runs the full relay bootstrap and token exchange, and adds load to the host that is already the bottleneck. Each of those extra passes is another chance to hit theNone-identity window above.Suggested fix
Separate "the cloud session is not available yet" from "the cloud session changed":
cloudSession.identityisNoneand there is no evidence of an account switch, fail with aConnectionTransientError(reason: "network", or a newsession-pending) so the supervisor uses normal backoff and the UI says reconnecting rather than telling the user to sign in.sessionChanged()for the real case: a captured identity whoseaccountIddiffers from the current one.accountIdrather than object reference inassertSession, so an object replacement for an unchanged account cannot produce the message.