Skip to content

fix: auto-recover PTY sessions after unexpected exit (WiFi drops)#17

Merged
wat-hiroaki merged 4 commits intomainfrom
fix/pty-session-auto-recovery
Mar 31, 2026
Merged

fix: auto-recover PTY sessions after unexpected exit (WiFi drops)#17
wat-hiroaki merged 4 commits intomainfrom
fix/pty-session-auto-recovery

Conversation

@wat-hiroaki
Copy link
Copy Markdown
Owner

Summary

Fixes PTY session recovery after WiFi disconnection or network errors.

Problem: When WiFi drops, Claude CLI exits with a network error. The session goes to error state and doesn't recover — even though claudeSessionId is preserved in the database. On manual restart, the conversation history was lost because --session-id doesn't restore context.

Root cause: Two issues:

  1. startSession always used --session-id (starts fresh) instead of --resume (restores conversation)
  2. No automatic retry logic on unexpected exit

Changes:

  • --resume for existing sessions: When agent.claudeSessionId already exists, use --resume <sessionId> instead of --session-id <sessionId>. This tells Claude CLI to restore the full conversation history.
  • Auto-recovery on unexpected exit: Up to 3 retry attempts with exponential backoff (2s → 4s → 8s). Recovery counter resets once the session becomes stable (active/thinking/tool_running).
  • Safety guards: Skips retry if user explicitly stopped the session (isKilled). Re-reads agent from DB before retry to avoid stale state.

Test plan

  • npm run lint — 0 errors
  • npx tsc --noEmit — clean
  • npm run build — clean
  • npm test — 13/13 pass
  • npm run dev — app starts without errors
  • QA: Start a session → disconnect WiFi → reconnect → verify auto-recovery with conversation history
  • QA: Verify max 3 retries (no infinite loop)
  • QA: Verify user-initiated stop doesn't trigger auto-recovery
  • QA: Verify fresh sessions (no prior sessionId) still use --session-id

Behavior summary

Scenario Before After
WiFi drop → reconnect Session dies, stays error Auto-retries up to 3x with backoff
Manual restart after crash New session (conversation lost) --resume restores conversation
User clicks Stop Goes to idle Goes to idle (no retry)
3+ consecutive failures N/A Stays error, no more retries

🤖 Generated with Claude Code

wat-hiroaki and others added 4 commits March 31, 2026 13:31
Two key changes:

1. Use `--resume <sessionId>` instead of `--session-id` when restarting
   a session that has an existing claudeSessionId. This restores the
   full conversation history after reconnection.

2. Add automatic retry on unexpected exit (non-zero, non-user-killed):
   - Up to 3 attempts with exponential backoff (2s, 4s, 8s)
   - Recovery counter resets once session becomes stable (active/thinking)
   - Skips retry if user explicitly stopped the session
   - Logs each attempt for debugging

Fixes the issue where WiFi disconnection caused Claude CLI to exit
with a network error, leaving sessions in 'error' state with no
way to automatically resume.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…dge cases

- Filter extraEnvVars through denylist before merging with plugin env
- Remove $ anchor from api.?key pattern to catch API_KEY_FILE variants
- Wire PluginPermissions into PluginManifest type

Closes #13

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add explanatory comment for DA response regex in utils.ts
- Clean up CHANGELOG v0.9.1 to remove duplicate entries

Closes #15

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
14 tests covering:
- --resume vs --session-id argument construction (5 tests)
- Auto-recovery counter with exponential backoff (4 tests)
- User-initiated stop does NOT trigger recovery (3 tests)
- Recovery counter resets on stable session (1 test)
- Scrollback persistence during recovery (1 test)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@wat-hiroaki wat-hiroaki merged commit ee451dc into main Mar 31, 2026
1 check failed
@wat-hiroaki wat-hiroaki deleted the fix/pty-session-auto-recovery branch April 6, 2026 01:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant