Skip to content

Thread from an offline T3 Connect environment cannot be settled, archived, or deleted from another device #24563

Open

Description

@DominikScholz

What happened

I had a thread that ran on my Windows laptop and showed up in the sidebar on my MacBook through T3 Connect. The thread was done but not yet settled. I turned the Windows laptop off. Afterwards I could not settle the thread from the MacBook: Settle, Delete and Archive all failed with a toast saying the machine is not connected. There was no way to get the thread out of my sidebar. I worked around it by turning the Windows laptop back on and settling from there. If I no longer had that machine, the thread would be stuck in the UI until I remove the whole connection.

Minor, but annoying: a thread that is already Done should not need its origin machine online just to be dismissed.

Diagnosis

This is the part of #4852 that the maintainer said was still open when closing it on 2026-10-21 ("stop, settle, archive, delete, pin, and snooze still require the environment to reconnect. If that part still matters to you, please open a new issue for that part only"). No follow-up issue exists yet, so this is it.

Mechanism in the build this happened on (nightly 0.1.3-nightly.20261024.3630, commit d53873b):

  • Settle, archive, delete, pin and snooze are environment commands. packages/client-runtime/src/state/threadCommands.ts wraps each in createEnvironmentCommand, which runs the command inside the environment that owns the thread (packages/client-runtime/src/state/runtime.ts).
  • Every RPC to that environment first resolves the current session in packages/client-runtime/src/rpc/client.ts:134-148. When the environment has no live session the call fails immediately with EnvironmentRpcUnavailableError: "<label> is not connected.". There is no local fallback, no queued delivery for when the peer reconnects, and no client-local per-thread hide state.
  • The thread row itself is a cached projection of the remote server's state. It renders as Offline (from fix(app): show threads from unreachable environments as offline #8935), so the display side is fine. Only the lifecycle actions are blocked.
  • The "Disconnect server" escape added in fix(web): disconnect offline servers from threads #11671 lives in the composer banner (apps/web/src/components/chat/useSystemComposerBanners.tsx) and only triggers for the active environment. It does not help when the offline environment is a secondary one whose single thread sits in the sidebar while you keep working on the local machine.
  • While the peer is offline the client also keeps sending server.reportClientActivity to it and fails every few seconds (279 failures in 45 minutes on this machine). Harmless, but it is the same code path and shows how noisy an offline peer is.

Expected: a thread whose environment is offline can be settled, archived, deleted or snoozed from another device, either applied locally and replayed when the peer reconnects, or at least hidden locally. Failing that, the actions should be disabled with a short "machine offline" note instead of a failing toast. PR #22768 (draft) proposes reversible local hiding and would cover this.

Steps to reproduce

  1. Machine A (macOS desktop app) and machine B (Windows desktop app) linked through T3 Connect.
  2. On B, run a thread to completion. Do not settle it.
  3. On A, confirm the thread is visible in the sidebar under its project.
  4. Shut down B.
  5. On A, wait until the thread row shows Offline, then try Settle, Archive, or Delete on it.

Result: each action fails with a toast <B> is not connected. The thread cannot be removed from the sidebar on A. Turning B back on and settling there is the only way out, apart from Settings → Connections → Remove, which drops the whole environment.

Version

0.1.3-nightly.20261024.3630 on both machines (desktop app).

Environment

Machine A: macOS 27.0.0 (darwin arm64), Node v24.22.0, T3 Code Nightly desktop app, local server 0.1.3-nightly.20261024.3630. Machine B: Windows laptop, T3 Code Nightly desktop app, same version. Linked via T3 Connect.

Evidence

# server.trace.ndjson on machine A while machine B is powered off (environment id truncated).
# Same failure class every RPC to the offline environment hits; the thread lifecycle commands
# go through the same EnvironmentRpc.currentSession check.
{"type":"otlp-span","name":"EnvironmentRpc.request","attributes":{"environment.id":"5a4edb53-…","rpc.method":"server.reportClientActivity"},
 "events":[{"name":"exception","attributes":{"exception.type":"EnvironmentRpcUnavailableError",
 "exception.message":"<windows laptop> is not connected.",
 "exception.stacktrace":"EnvironmentRpcUnavailableError: <windows laptop> is not connected.\n    at onNone (t3code://app/assets/runtime-CAtAZZ0F.js:5:29927)\n    at EnvironmentRpc.currentSession (t3code://app/assets/runtime-CAtAZZ0F.js:5:30640) ..."}}]}

# 279 such failures between 22:18 and 23:03 local while the peer was off (one every ~10 s).

Source, commit d53873b:

packages/client-runtime/src/rpc/client.ts:134-148   currentSession -> EnvironmentRpcUnavailableError "<label> is not connected."
packages/client-runtime/src/state/threadCommands.ts:198-224   delete/archive/settle are createEnvironmentCommand(...)
packages/client-runtime/src/state/runtime.ts:732   createEnvironmentCommand -> runInEnvironment(target.environmentId, ...)

Related issues

#4852 (closed completed on 2026-10-21; this is the explicitly requested follow-up for the still-open part), #8924 and #12140 (closed as duplicates of #4852, same symptom), #8935 (Offline rendering, merged), #11671 (Disconnect server for the active environment only), #22768 (open draft PR for local hiding), #22887 (open PR, reorder around offline rows). Not a duplicate: #4852 is closed and its maintainer asked for a new issue for exactly this part.

Fix applied or workaround

Nothing changed on the machine. Workaround used: power the origin machine back on and settle from there. Alternative: Settings → Connections → Remove, which removes the environment and all its cached threads.

Filed by

Claude Fable 5.1 (claude-fable-5-1) in Claude Code, via t3 triage.

Activity

  1. noyex commented on Oct 30, 2026

    @noyex

    Still reproduces on 0.1.5-nightly.20261029.3877 (macOS desktop). Threads from a powered-off machine stay in the sidebar and the context menu greys out Pin, Settle, Snooze, Rename and Archive, so there is no way to get them out of the list. Even a local-only hide (or collapsing offline-environment threads into a separate group) would solve it for me.

  2. codewarnab commented on Nov 2, 2026

    @codewarnab

    Hitting this too, with one variant that may matter: the environment died mid-run, not while a thread was already done.

    Setup: headless Ubuntu 24.04 (arm64) Oracle Cloud VM running the T3 Code server as a remote environment (0.1.7-nightly.20261102.4066), connected from my other device. The VM was shut down while a thread was actively running.

    Result:

    • The thread shows Working 15h+ in the sidebar. Since the run never got a terminal event on the machine, it doesn't transition to Done/Failed/Offline — it just keeps counting as Working.
    • Settle fails with Failed to settle thread — This connection cannot change threads or projects. (the web variant of the <machine> is not connected wall described in the diagnosis above).
    • No Resume path is offered. The only way out is to power the VM back on and let it reconnect, which is not always possible (spot-preempted VMs, reimaged boxes, etc.).

    Why this differs slightly from the main repro here: with a thread that was already Done before the machine went offline, the run state is final and the sync-back behavior is unambiguous. Here the last known state is "running", so the client keeps rendering it as Working indefinitely rather than showing an Offline/Interrupted state.

    Proposal: fold this into the fix — when an environment goes offline mid-run, locally render its in-flight turn as Interrupted (instead of Working), offer Settle/Delete/liberate locally with replay-on-reconnect (per the proposal in #4852), and offer Resume once the environment is back. That covers both flavors: done-threads that need dismissal, and mid-run threads that need to be marked dead.

    Happy to capture server-side logs from the VM when this happens again — the repro is on-demand (shut the VM down mid-run).

  3. jux310 commented on Nov 2, 2026

    @jux310

    Same bug on stable 0.1.6 (macOS desktop app, darwin arm64), with two details not covered above:

    1. Misleading error text. Clicking Settle on a thread whose host is disconnected fails with
      Failed to settle thread: This connection cannot change threads or projects.
      instead of " is not connected." In v0.1.6, useOrchestrationCommand
      (apps/web/src/state/use-orchestration-command.ts:24) checks AuthOrchestrationOperateScope
      via readEnvironmentScope before the RPC runs. With no live session for the offline host,
      sessionHasScope returns false, so the user sees a permission error rather than an offline one.
    2. Row Settle button still offered. The hover "Settle" button in the sidebar row is gated only on
      settlementSupported (SidebarThreadRow.tsx:1334, which comes from cached server config), not on
      canOperateThread like Pin and Snooze (lines 930, 1093). So the button appears for an offline
      host and always fails.

    Also, auto-settle runs on the owning server's sweep, so threads from an offline host never
    auto-settle either, and they sit in the sidebar until the host comes back.

    Version: client 0.1.6 desktop; the offline host's version is unknown.
    Screenshots attached (anonymized).

    Added by Claude Opus 5.5 (claude-opus-5-5) in Claude Code, via t3 triage.

  4. Byntham commented on Nov 10, 2026

    @Byntham
    Contributor

    Note

    🤖 Claude Opus 5.5 responding on behalf of Byntham

    #24917 fixes the settle and snooze part of this. It queues them while the machine is offline and sends them on reconnect. It also removes the false "This connection cannot change threads or projects." error for a machine that has been offline since the client loaded.

    Two things it leaves open here, from reading its diff at the current head:

    • Archive and delete stay disabled offline. Its menu test asserts both are disabled without a loaded session. This issue asks for them too, so it shouldn't close when fix: settle and snooze threads while their machine is offline #24917 merges.
    • The mid-turn case is worth confirming. For a thread cached as running or waiting on a request, applySettle returns the thread unchanged until the server accepts. That's the "Working 15h+" case from the earlier comment. The settle queues, but the row may give no sign of it until the machine is back.
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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions