github / github/copilot-cli

[Bug] Autopilot write operations silently fail with "Permission denied and could not request permission from user" after VS Code SSH dev container network reconnect, causing infinite retry loop

Open
#2,971 0 comments 2 reactions 0 assignees View on GitHub
area:agents area:permissions
Dominant language
Shell
Stars
11.2k
Forks
1.9k
Avg merge
14h 16m
Merged PRs (30d)
6

Description

### Describe the bug

In a **VS Code Remote SSH dev container** environment, all write-capable tool calls (`apply_patch`, `bash` with file writes/redirects, even writing to `/tmp`) permanently fail with:

```
Permission denied and could not request permission from user (code: "denied")
```

even though the session is in **autopilot mode** and read-only tools (`view`, `rg`, `glob`, `bash` with `ls`/`pwd`) continue to work normally.

The agent has no way to distinguish a transient IPC failure from a genuine permission refusal, so it enters an **infinite retry loop**: it rewrites the same content, changes paths (absolute → relative), tries fallback directories, delegates to sub-agents, and regenerates the document from scratch — all without ever succeeding. The session consumed **435 premium requests over ~24 minutes** before the user manually aborted it.

**Root cause hypothesis:** The VS Code extension communicates with the Copilot CLI process via an IPC channel (Unix socket / pipe). When a brief SSH network disconnect occurs and VS Code reconnects, the CLI process retains the stale file descriptor while the extension has moved to a new connection. Any subsequent permission-check RPC from the CLI to the extension silently fails, returning "denied" because the channel has no live handler on the other end. Read-only tools bypass this channel and continue working; write tools always go through it, so they all fail permanently for the rest of the session.

**Evidence from `events.jsonl`:**

| Time (UTC) | Event |
|---|---|
| 05:31:58 | `session.start` + `session.mode_changed: interactive → autopilot` |
| 05:32 – 05:33:45 | 50+ read-only tool calls (`view`, `rg`, `glob`) all succeed |
| 05:34:10 | First `apply_patch` → **denied** (very first write attempt) |
| 05:34:27 | `bash touch /workspaces/cat/todo/.../.write-test` → **denied** |
| 05:34:38 | `bash ls -ld todo/...` → **succeeds** (read-only) |
| 05:34:44 | `bash printf 'test' > /tmp/copilot-write-test` → **denied** (even `/tmp`) |
| 05:34 – 05:58 | Agent retries write in 18 different ways, all denied |
| 05:50:21 | Context compaction (196k tokens) |
| 05:58:49 | User aborts |

Key observation: `callId` prefix is `custom_call_*` for `apply_patch` (routed via VSCode extension) and `call_*` for `bash`, yet **both** fail for writes and succeed for reads. This points to the write-permission-check path in the CLI itself being broken, not the extension routing.

### Affected version

```
GitHub Copilot CLI 1.0.36
```

### Steps to reproduce the behavior

1. Open a project in VS Code with a **Remote SSH** dev container (Debian/Ubuntu).
2. Start a Copilot CLI autopilot session: `copilot` → select autopilot mode.
3. While the session is running and actively using only read-only tools, **briefly disconnect and reconnect the SSH/VS Code Remote connection** (e.g., suspend laptop, VPN reconnect, or network blip).
4. Ask the agent to create or modify a file (e.g., `apply_patch` or `bash` with a redirect).
5. Observe that **every write operation** immediately returns `Permission denied and could not request permission from user` while read operations continue to work.
6. The agent enters an infinite retry loop with no exit condition.

### Expected behavior

One of the following should happen after the permission IPC channel is detected as broken:

1. **Autopilot mode should pre-approve all write operations** without requiring a live IPC round-trip. If the channel is unavailable, writes should fall through to the pre-granted autopilot permissions rather than failing to "denied".
2. **Alternatively**, the CLI should detect that the IPC channel is broken (connection error, timeout, or EOF) and surface a clear, actionable error to the user (e.g., "Permission channel lost — run `/allow-all` or restart the session") rather than returning a generic `denied` that the agent treats as a content-level refusal.
3. **The agent should have a maximum retry budget for write operations** and stop the session (or surface a blocking question to the user) when it cannot make forward progress due to persistent permission failures, rather than looping indefinitely.

### Additional context

- **OS:** Debian GNU/Linux 12 (bookworm) inside a VS Code Remote SSH dev container
- **CPU architecture:** x86_64
- **Terminal emulator:** VS Code integrated terminal (over SSH)
- **Shell:** bash
- **VS Code version:** 1.x with GitHub Copilot Chat extension
- **Session archive:** Full `events.jsonl` (5.3 MB, 793 events) and `session.db` are available locally at `/root/.copilot/session-state/adf2be49-a454-4ced-b7bc-3cbfe4fc774e/`

**Session statistics at shutdown:**
```
totalPremiumRequests: 435
totalApiDurationMs: 1,558,676 ms (~26 min)
linesAdded: 0 (zero bytes written despite 24 min of attempts)
filesModified: []
```

**Related issue:** #1810 describes the `/allow-all` dialog not appearing when switching to autopilot. The current bug is a more severe variant: the permission channel breaks mid-session after a network reconnect, with no recovery path and no user-visible indication.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.