Skip to content

[Bug]: iOS messages queued as "Sends on reconnect" are not sent while the target environment shows Connected #13995

Closed as duplicate

Description

@gmelvill

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/mobile

Steps to reproduce

  1. In the iOS app (1.3.0), connect to a desktop environment directly over a private HTTPS address. Also have two T3 Connect environments enabled whose machines are currently powered off.
  2. Send messages to threads on the directly connected environment during a brief connection drop.
  3. The messages appear under Unsent as "Sends on reconnect".
  4. Wait for the environment to reconnect.

Expected behavior

Queued messages send as soon as their target environment is connected again.

Actual behavior

At 05:03–05:04 (UTC+10) the Environments sheet showed the target environment as Connected, while two messages to it were still listed as "Sends on reconnect". A persistent "Reconnecting 2 environments" banner was showing because the two T3 Connect machines were offline. The host then restarted for an update (unreachable 05:05:58–05:08:27). The first queued message only reached the host at 05:13:57, about 5½ minutes after the host was back and about 10 minutes after it was written.

Possible cause (a guess, not verified in the client code): the outbox may wait for all environments to reconnect, so offline T3 Connect machines hold back messages for an environment that is online.

Impact

Major degradation or frequent failure

Version or commit

iOS app 1.3.0 (85); desktop 0.0.43-nightly.20260927.2344

Environment

iPhone, iOS 27; Windows 11 host over Tailscale Serve HTTPS; two T3 Connect environments offline

Logs or stack traces

Host server trace (UTC+10):

  • 05:03:26 SessionStore.recordClientConnection / markConnected for the phone. No orchestration.dispatchCommand follows.
  • 05:05:58 → 05:08:27 backend restart for the desktop update.
  • 05:08:27 onward: repeated client reconnects succeed.
  • 05:13:57 first orchestration.dispatchCommand / startThreadTurn for a held message.

Workaround

None found; the messages eventually sent on their own.

Activity

  1. juliusmarminge commented on Sep 27, 2026

    @juliusmarminge
    Member

    Triage

    The outbox does not wait on every environment. "Sends on reconnect" under Unsent is the static label for a queued new task (ThreadListV2PendingRow). It stays that text even after the target environment is connected. Follow-ups on an existing thread do not use it; those show a queued icon on the thread row.

    A queued new task is eligible to send only when that environment's connection phase is connected and its shell status is live (resolveThreadOutboxDeliveryAction in apps/mobile/src/state/thread-outbox-model.ts). Anything else is wait, and the drain moves on to the next queue. Powered-off T3 Connect environments are not a global lock. The "Reconnecting 2 environments" banner is only the count of environments whose phase is connecting or reconnecting (workspaceConnectionStatusLabel). That label is chosen ahead of "Syncing threads...", so a shell that is still synchronizing on the connected machine is hidden while any other environment is reconnecting.

    "Connected" on the environment row is the supervisor phase after the websocket is up and the server-config snapshot has arrived. It does not mean the shell subscription has reached live. Until it does, a new task stays queued and the client never calls startThreadTurn. That matches the host trace: markConnected at 05:03:26 with no orchestration.dispatchCommand, then the desktop restart at 05:05:58–05:08:27, then the first startThreadTurn only at 05:13:57.

    Outbox retry delay and connection backoff both cap at 16 seconds, so this is not a five-minute timer. credentials-changed only drops relay targets, so the offline T3 Connect supervisors do not reset the direct Tailscale session. A session can sit in shell synchronizing after the row already says Connected (HTTP shell snapshot gives up after 20 seconds and the socket catch-up has no matching client deadline). The "repeated client reconnects" after 05:08:27 would also keep resetting that shell to synchronizing before the send gate opens.

    This is a real stall: a queued new task can sit for minutes while its environment shows Connected. The offline machines explain the banner, not the hold. The useful next trace is why that client kept opening new sessions from 05:08:27 until 05:13:57 (session close reasons on the host, or the phone's [t3-thread-outbox] log).

  2. added
    bugSomething is broken or behaving incorrectly.
    via-triageFiled through npx t3 triage
    on Sep 27, 2026
  3. gmelvill commented on Sep 27, 2026

    @gmelvill
    Author

    Thanks. On the reconnects between 05:08:27 and 05:13:57: that trace window has rotated out on this host (about 40 minutes of server.trace.ndjson retention), so I can't recover the session close reasons for it. I'll capture the host side promptly at the next desktop update. The iOS client is identifiable by user agent T3Code/85, so I can separate its connects/disconnects and shellSnapshot timing from the other clients.

  4. gmelvill commented on Sep 28, 2026

    @gmelvill
    Author

    Possibly related host-side data is in #13994 (comment). On this Windows host, GET /api/orchestration/shell took 53–64 s (in resolveRepositoryIdentitiesForProjects, slowed by degraded Windows process cleanup), while the mobile clients cancelled it at about 6 s. That fits your explanation that the shell never reached live, so the queued send stayed held.

    — Geoff. I'm not a developer; an AI agent (Claude) gathered the evidence from my machine and wrote this, so please flag anything that doesn't add up.

  5. gmelvill commented on Oct 22, 2026

    @gmelvill
    Author

    Haven't seen this again recently.

    • iOS app T3 Code 2.0.0 (122), com.t3tools.t3code; desktop 0.1.2-nightly.20261021.3499 (Windows 11, Tailscale Serve).

    No recording or trace to add, as it hasn't recurred. If it does, I'll try disabling only the offline T3 Connect environments, as you suggest, and post a timestamped recording of Unsent and the target's Connected status with the matching host trace.

  6. added
    needs more infoInitial triage showed no bug. Awaiting more info
    and removed
    needs more infoInitial triage showed no bug. Awaiting more info
    on Oct 22, 2026
  7. juliusmarminge commented on Nov 12, 2026

    @juliusmarminge
    Member

    This is the same problem as #2829, so I'm closing it in favour of that one. If it is different, say how and it will be reopened.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions