microsoft / microsoft/vscode

VS Code window killed by macOS (killed, code 9) when Copilot Agent edits .json5 files

Open
#336,730 0 comments 0 reactions 1 assignee Assigned to @hediet View on GitHub
Dominant language
TypeScript
Stars
193k
Forks
42.4k
PR merge metrics
PR metrics pending

Description

## Summary

In a multi-folder workspace, when using Copilot Agent to edit code and the Agent's editing scope involves a `.json5` file (e.g. `buildinfo.json5`), the VS Code window is forcibly terminated by the macOS kernel after approximately 20 seconds, with the error message "The window terminated unexpectedly (reason: 'killed', code: '9')".

Once this issue first occurs, every subsequent Agent prompt in the workspace reliably triggers the crash. Restarting VS Code does not resolve it. I have recorded 7 crashes across 2 log sessions, all following an identical error pattern.

## Log Collection Script & Captured Logs

### Log collection script

```bash
#!/bin/bash
# collect_crash_logs.sh — Collect VS Code crash-related logs
# Usage: ./collect_crash_logs.sh [log session directory name]

LOG_BASE="$HOME/Library/Application Support/Code/logs"
SESSION="${1:-$(ls -t "$LOG_BASE" | head -1)}"
SESSION_DIR="$LOG_BASE/$SESSION"

echo "=== Log session: $SESSION ==="

# 1. main.log — crash records
echo "========== main.log (crash records) =========="
cat "$SESSION_DIR/main.log" 2>/dev/null | grep -i "kill\|crash\|renderer.*gone"

# 2. Per-window exthost.log — changeLanguage error stats
for w in "$SESSION_DIR"/window*; do
WNAME=$(basename "$w")
ERR_COUNT=$(cat "$w/exthost/exthost.log" 2>/dev/null | grep -c "changeLanguage")
if [ "$ERR_COUNT" -gt 0 ]; then
echo ""
echo "========== $WNAME/exthost.log =========="
echo "changeLanguage error count: $ERR_COUNT"
echo ""
echo "--- First error ---"
cat "$w/exthost/exthost.log" 2>/dev/null | grep -B1 "changeLanguage" | head -4
echo ""
echo "--- Last error ---"
cat "$w/exthost/exthost.log" 2>/dev/null | grep -B1 "changeLanguage" | tail -4
echo ""
echo "--- Non-changeLanguage errors ---"
cat "$w/exthost/exthost.log" 2>/dev/null | grep -E "^\d{4}" | grep -v "changeLanguage" | grep -v "NOT found" | head -10
fi
done

# 3. renderer.log — "unexpected error" time range
echo ""
echo "========== renderer.log =========="
for w in "$SESSION_DIR"/window*; do
WNAME=$(basename "$w")
ERR_COUNT=$(cat "$w/renderer.log" 2>/dev/null | grep -c "出现未知错误\|An unexpected error")
if [ "$ERR_COUNT" -gt 0 ]; then
echo "--- $WNAME ---"
echo "Unexpected error count: $ERR_COUNT"
cat "$w/renderer.log" 2>/dev/null | grep "出现未知错误\|An unexpected error" | head -1
cat "$w/renderer.log" 2>/dev/null | grep "出现未知错误\|An unexpected error" | tail -1
fi
done
```

### Captured logs (sanitized)

**main.log — crash records:**

```
2026-09-18 15:57:43.401 [error] CodeWindow: renderer process gone (reason: killed, code: 9)
2026-09-18 16:19:49.526 [error] CodeWindow: renderer process gone (reason: killed, code: 9)
```

**exthost.log — changeLanguage errors (7 crashes summary):**

| Crash | Window | Timestamp | changeLanguage errors |
|-------|--------|-----------|---------------------|
| 1 | window4 | 14:15:09 | 2,768 |
| 2 | window5 | 15:32:41 | 4,506 |
| 3 | window6 | 15:36:35 | 4,554 |
| 4 | window7 | — | 2,442 |
| 5 | window1 | 15:41:46 | 2,869 |
| 6 | window1 | 15:57:43 | 2,386 |
| 7 | window3 | 16:19:49 | 1,681 |

**exthost.log — error sample (sanitized paths):**

```
2026-09-18 16:19:47.674 [error] Error: document 'chat-editing-snapshot-text-model:
///entry/src/main/resources/rawfile/buildinfo.json5
?{"session":{"$mid":1,"external":"vscode-chat-session://local/",
"path":"/","scheme":"vscode-chat-session","authority":"local"},
"requestId":"request_","undoStop":"__epoch_22",
"scheme":"file","authority":""}' NOT found
at XP.changeLanguage (extensionHostProcess.js:667:7776)

2026-09-18 16:19:47.676 [error] Error: document 'chat-editing-snapshot-text-model:
///entry/src/main/resources/rawfile/buildinfo.json5?{...}' NOT found
at XP.changeLanguage (extensionHostProcess.js:667:7776)

... (repeats 1,681 times in ~2 seconds)
```

**exthost.log — non-changeLanguage errors:**

```
2026-09-18 16:19:48.369 [info] Extension host terminating: renderer closed the MessagePort
2026-09-18 16:19:48.613 [error] An error occurred when disposing the subscriptions
for extension 'NailyZero.vscode-naily-ets':
2026-09-18 16:19:48.613 [error] AggregateError: Encountered errors while disposing of store
2026-09-18 16:19:48.667 [error] Error: Channel has been closed
```

**renderer.log — 20 seconds before crash:**

```
2026-09-18 16:19:28.323 [error] An unexpected error occurred. See logs for details.
2026-09-18 16:19:29.323 [error] An unexpected error occurred. See logs for details.
2026-09-18 16:19:30.345 [error] An unexpected error occurred. See logs for details.
... (once per second for ~20 seconds)
2026-09-18 16:19:47.456 [error] An unexpected error occurred. See logs for details.
```

**renderer.log — other logs before crash:**

```
2026-09-18 16:19:14.163 [info] Extension host (LocalProcess pid: 71977) is unresponsive.
2026-09-18 16:19:14.957 [info] UNRESPONSIVE extension host: starting to profile NOW
2026-09-18 16:19:14.957 [info] Extension host (LocalProcess pid: 71977) is responsive.
2026-09-18 16:19:15.010 [warning] UNRESPONSIVE extension host: 'vscode.json-language-features'
took 22.96% of 0.276ms
```

**Per-second error burst frequency (crash #7):**

```
16:19:47 → 421 errors/sec (burst begins)
16:19:48 → 1,196 errors/sec (peak, Extension host begins terminating)
16:19:49 → 68 errors/sec (process SIGKILLed)
```

**Key evidence — all errors point to the same request:**

```
requestId: request_ (all identical)
undoStop: __epoch_22 (all identical)
file: buildinfo.json5 (only file involved)
```

## AI Root Cause Analysis

The crash is caused by an infinite loop triggered by a race condition between `chat-editing-snapshot` and `changeLanguage`.

**Mechanism:**

1. Copilot Agent initiates an edit on a `.json5` file in the workspace
2. The `chat-editing-snapshot-text-model` mechanism creates a snapshot document for the file
3. The snapshot document is immediately disposed (or not properly registered in the document registry)
4. `XP.changeLanguage` attempts to switch the language mode on the snapshot document (`.json5` → JSON)
5. Since the document no longer exists, it throws a `"document '...' NOT found"` error
6. The caller catches the error and immediately retries, forming an infinite loop
7. ~1,600–4,500 identical errors accumulate in ~2 seconds, causing memory to spike
8. macOS jetsam detects memory pressure and sends SIGKILL (signal 9)

**Key evidence:**

- All 7 crashes follow an identical error pattern, all targeting `.json5` files
- Within a single crash, all errors share the same `requestId` and `undoStop`, confirming a single edit request triggers the entire infinite retry
- Error frequency rapidly escalates from 421/sec to 1,196/sec, consistent with an infinite loop
- `.json5` files are handled by the `vscode.json-language-features` built-in extension; `changeLanguage` attempts to switch the `.json5` language mode to JSON, and this switching path has a race condition on snapshot documents

**Distinction from existing fixed issues:**

- **#326913**: Same SIGKILL symptom, but root cause is Mach port exhaustion, not a `changeLanguage` loop
- **#296064**: Parent issue for chat editing crashes; PR #336095 fixed renderer-freeze but does not cover this path
- **#324549**: Chat editing checkpoint crash via a different code path (`pieceTreeTextBuffer`)
- **PR #331840**: Prevents agent from editing snapshot copies, but does not address the `changeLanguage` retry loop

## Suggested Fix Directions

1. **Precondition check**: Before calling `XP.changeLanguage`, check whether the target document still exists in the document registry. If it does not exist, skip the operation to avoid executing actions on disposed documents.

2. **Error handling termination**: When `changeLanguage` throws a `"document NOT found"` error, the retry should terminate rather than continue looping. The current retry logic lacks judgment for this type of unrecoverable error, treating a permanent error (document does not exist) as a transient one.

3. **Retry limit / circuit breaker**: Add a maximum retry count or circuit breaker to the retry logic for `changeLanguage`, so that even if an unexpected loop occurs, it can be interrupted before errors accumulate to dangerous levels, preventing memory spikes from causing the process to be killed.

4. **Fix snapshot document lifecycle**: Investigate why the snapshot document created by `chat-editing-snapshot-text-model` is disposed before `changeLanguage` executes, and ensure the snapshot document's lifecycle covers all operations performed on it.

Contributor guide

Open the contributing guide

Research direction

Start at XP.changeLanguage in extensionHostProcess.js and trace the vscode.json-language-features path for chat-editing-snapshot-text-model documents. Reproduce the .json5 Copilot Agent edit and inspect the repeated changeLanguage errors around the shared requestId and undoStop. Done means the disposed-document path no longer produces an unbounded error burst or kills the VS Code window.

Written by the indexing model from the issue text.

Assessment

Tech stack
macos, typescript, vscode
Domain
desktop, devtools, performance
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.