Skip to content

Bug: Remote SSH Workspace becomes unusable after auto-continue limit is reached #67

Closed

Description

@malys

Summary

On a Remote SSH Workspace, the agent sometimes reaches the auto-continue limit:

Auto-continuing (1/3) - resuming on remote...
Auto-continuing (2/3) - resuming on remote...
Auto-continuing (3/3) - resuming on remote...
Agent did not complete after 3 auto-continues

After this happens, the chat no longer responds.

Using "Restart Session" does not recover the conversation.

Environment

  • Claude Code Studio v7.8
  • Windows 11
  • Remote SSH Workspace
  • Linux remote host

Steps to Reproduce

  1. Open a Remote SSH Workspace.
  2. Start a conversation or task.
  3. Wait until auto-continue is triggered.
  4. Let the retries reach 3/3.
  5. Observe the failure message.
  6. Try "Restart Session".

Actual Behavior

  • Auto-continue reaches its limit.
  • The agent stops responding.
  • Restart Session does not recover the chat.
  • No obvious recovery mechanism is available.

Expected Behavior

  • The chat should remain usable after the failure.
  • Restart Session should fully recover the agent.
  • The SSH session should be reconnected automatically when possible.
  • The user should be able to continue the conversation without creating a new chat.

Suggestions

  • Display the root cause of the failure.
  • Show SSH connection status.
  • Add a "Reconnect SSH Session" action.
  • Automatically recreate the remote agent when the SSH connection is still available.
  • Provide more detailed logs when auto-continue fails.

Impact

This is disruptive for long-running tasks on remote SSH workspaces because the conversation becomes permanently stuck and must often be recreated from scratch.

High

Activity

  1. Lexus2016 commented on Aug 24, 2026

    @Lexus2016
    Owner

    Thanks for the detailed report — the reproduction steps and the exact log lines made this findable.

    The auto-continue limit turned out to be a red herring. The real defect is a missed termination in the SSH transport, and it explains both symptoms at once.

    runSshSingle() awaits a promise that resolves only from the transport's onDone. Four paths in ClaudeSSH.send() ended a run without ever reaching it:

    1. A cleanly closed socket emits no 'error'. sshd's ClientAliveCountMax/LoginGraceTime drop, a NAT/firewall idle-reap on a long-running turn, and the client's own conn.end() all land on 'close' — and there was no conn.on('close') handler at all.
    2. The idle watchdog and the hard cap called conn.end() and nothing else. That only settles a run when a channel is open for ssh2 to tear down with it.
    3. The abort listener was registered inside the conn.exec callback, so a Stop pressed while the connection was still handshaking was silently ignored.
    4. conn.on('error') called onDone directly, bypassing the once-guard, so the socket close behind it fired it a second time.

    A pending await keeps the session's activeTasks entry alive, and nothing reaps it — the 15s orphan sweeper opens with if (activeTasks.has(sid)) continue. That is why the chat stopped accepting messages and why Restart Session did nothing: it was hitting "Task is still running" and returning early. Only a server restart cleared it.

    Fixed in #68:

    • Every way a remote run can end now goes through finish(), and the abort listener is registered before the connection is opened — so Stop always works, and a dropped link always ends the turn instead of hanging it.
    • Restart Session is now a recovery action, not a refusal. It aborts the live turn, waits for it to release the session, reaps it if it never does, and drops the cross-connection lock with it.
    • It is reachable without a working turn. The in-message button only rendered when the server managed to send a session_restart_available frame — and the run that needs recovering is precisely the one that never sends one. There is now a 🔄 Restart button in the session bar whenever the chat has a Claude session.
    • You do not lose the conversation. Restart clears claude_session_id, and the next message replays this chat's full history into the fresh remote session. That part already existed; it just was not reachable.
    • The failure message names the root cause. Instead of only "Agent did not complete after 3 auto-continues", it now says why — hitting the per-run turn limit (raise Max turns) reads differently from the SSH link failing, and those need different fixes from you.

    Two regression suites were added: one drives the SSH transport through a fake ssh2 client and asserts onDone fires exactly once across eight ways a run can end (the first scenario hangs on the old code), and one boots a real server against a claude that never exits and pins that a restart aborts and releases the session.

    Two of your suggestions I did not implement, so you know where things stand: there is no persistent SSH connection-status indicator, and no automatic re-creation of the remote agent. The connection is opened per run rather than held, so there is no long-lived state to display or revive — a failed turn now reports the SSH error inline instead. If you would still find a status indicator useful, a separate issue for it is welcome.

    Please reopen if you hit anything like this again after the next release.

  2. malys commented on Aug 25, 2026

    @malys
    Author

    7.9.0
    "⚠️ Agent did not complete after 3 auto-continues — it kept hitting the per-run turn limit (raise "Max turns" for this chat). The chat is still usable: send another message to continue, or use Restart Session to start a fresh remote session with this chat's history replayed."
    Restart session -> no effect

    ⏳ Auto-continuing (1/3) — resuming on remote...

    I'll read the catalog files to see what conditions and actions already exist.

    ⏳ Auto-continuing (2/3) — resuming on remote...

    ⏳ Auto-continuing (3/3) — resuming on remote...

    ⚠️ Agent did not complete after 3 auto-continues — it kept hitting the per-run turn limit (raise "Max turns" for this chat). The chat is still usable: send another message to continue, or use Restart Session to start a fresh remote session with this chat's history replayed.
    ✅ Done — 8 calls
    $0.643 · 4 in / 804 out · 3 turns · 4% ctx · 12.9s
    Done

    @Lexus2016 issue not solved

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

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions