Skip to content

Instantly share code, notes, and snippets.

@blurman-ai
Last active July 4, 2026 11:15
Show Gist options
  • Select an option

  • Save blurman-ai/8a782c711befe6fb6c4c94f73a90c98f to your computer and use it in GitHub Desktop.

Select an option

Save blurman-ai/8a782c711befe6fb6c4c94f73a90c98f to your computer and use it in GitHub Desktop.
VS Code Codex infinite spinner fix: reset corrupted webview state

Fix VS Code Codex infinite spinner when the CLI still works

Symptom

Codex works from the terminal:

codex

But the VS Code Codex panel stays on an infinite spinner and the chat never appears. The backend, the CLI, and auth can all be fine, and reinstalling the extension changes nothing.

Confirmed root cause

Corrupted VS Code webview state in:

~/.config/Code/Local Storage
~/.config/Code/Session Storage

The webview service worker serves a truncated JavaScript bundle for the Codex panel. The bundle on disk is valid, but the webview receives a broken copy and fails with:

Uncaught SyntaxError: Unexpected end of input

The frontend never mounts, so the panel stays on the spinner. This belongs to a recurring family of VS Code webview cache/state problems that VS Code does not clean up on its own.

Key diagnostic step

Run VS Code with a clean user profile:

code --user-data-dir=/tmp/vscode-clean

If Codex works there, the cause is local VS Code profile state, not the CLI, account, network, or extension binary.

Quick fix

Close VS Code completely, then run:

mv ~/.config/Code/"Local Storage"   ~/.config/Code/"Local Storage.bak.$(date +%Y%m%d_%H%M%S)"
mv ~/.config/Code/"Session Storage" ~/.config/Code/"Session Storage.bak.$(date +%Y%m%d_%H%M%S)"

Reopen VS Code. The folders regenerate on start.

Script

codex_fix.sh from this gist does the same cleanup with safety checks and a rollback path:

  • checks that VS Code is closed;
  • verifies the installed openai.chatgpt extension;
  • checks the Codex webview JavaScript assets;
  • removes regenerable webview caches;
  • moves Local Storage and Session Storage to .bak;
  • offers a check mode after reopening VS Code.

Run:

bash ~/codex_fix.sh

After reopening VS Code:

bash ~/codex_fix.sh check

What did not fix it

None of these was the root cause:

  • reinstalling the Codex extension;
  • clearing the ordinary VS Code cache alone;
  • checking VPN/network;
  • checking the auth token;
  • removing ~/.codex/.tmp;
  • a plugin manifest warning in the logs;
  • rebooting the machine;
  • downgrading the extension.

The decisive test was the clean VS Code profile.


Copyright 2026 Sergey Blekher. Shared as-is; use and adapt freely.

#!/usr/bin/env bash
# =====================================================================
# codex_fix.sh
#
# Diagnose and reset the VS Code webview state used by the Codex panel
# from the openai.chatgpt extension.
#
# Symptom:
# Codex works in the terminal, but the VS Code Codex panel stays on an
# infinite spinner and the chat UI never appears.
#
# Confirmed root cause, 2026-07-04:
# Corrupted VS Code webview state in:
#
# ~/.config/Code/Local Storage
# ~/.config/Code/Session Storage
#
# The VS Code webview service worker served a truncated JavaScript bundle
# for the Codex panel. The file on disk was valid, but the webview received
# a broken version and failed with:
#
# Uncaught SyntaxError: Unexpected end of input
#
# Result: the Codex frontend did not mount, so the panel stayed on the
# spinner.
#
# Important diagnostic:
# Run VS Code with a clean profile:
#
# code --user-data-dir=/tmp/vscode-clean
#
# If Codex works there, the problem is not the Codex CLI, account, auth,
# network, extension binary, or model list. It is local VS Code profile
# state.
#
# What this script does:
# - checks that VS Code is closed;
# - finds the openai.chatgpt extension;
# - checks webview JavaScript assets;
# - deletes regenerable webview cache directories;
# - moves Local Storage and Session Storage to .bak;
# - provides a check mode after reopening VS Code.
#
# Usage:
# 1. Close VS Code completely.
# 2. Run:
#
# bash ~/codex_fix.sh
#
# 3. Open VS Code and open the Codex panel.
# 4. Run:
#
# bash ~/codex_fix.sh check
#
# Notes:
# - Cache directories are deleted because VS Code regenerates them.
# - State directories are moved to .bak so rollback is possible.
# =====================================================================
set -uo pipefail
CFG="$HOME/.config/Code"
EXT="$(ls -dt "$HOME"/.vscode/extensions/openai.chatgpt-* 2>/dev/null | head -1)"
# Regenerable cache directories. These are removed.
CACHE_DIRS=(
"Service Worker"
"CachedData"
"Code Cache"
"GPUCache"
"WebStorage"
)
# Webview state directories. These are moved to .bak.
STATE_DIRS=(
"Local Storage"
"Session Storage"
)
# Asset name fragment from the observed webview console error.
ASSET_HINT="thread-side-panel-tabs"
print_section() {
printf '\n== %s ==\n' "$1"
}
info() {
printf 'INFO: %s\n' "$1"
}
ok() {
printf 'OK: %s\n' "$1"
}
warn() {
printf 'WARN: %s\n' "$1"
}
error() {
printf 'ERROR: %s\n' "$1"
}
newest_codex_log() {
local log_root
log_root="$(ls -dt "$CFG"/logs/*/ 2>/dev/null | head -1)"
echo "${log_root}window1/exthost/openai.chatgpt/Codex.log"
}
check_mode() {
print_section "CHECK: state after restarting VS Code"
if pgrep -x code >/dev/null; then
ok "VS Code is running. This is expected in check mode."
else
warn "VS Code is not running. Open VS Code and the Codex panel, then run check again."
fi
print_section "Latest Codex extension log"
local log_file
log_file="$(newest_codex_log)"
if [[ -f "$log_file" ]]; then
info "Log file: $log_file"
echo "-----"
tail -25 "$log_file" | sed 's/^/ /'
echo "-----"
if grep -q "Initialize received" "$log_file"; then
ok "The app-server initialized."
else
warn "No initialization marker found in the latest log."
fi
else
error "Codex.log was not found. The extension may not have activated."
fi
print_section "App-server process"
if pgrep -af "openai.chatgpt.*app-server" >/dev/null; then
ok "App-server process found:"
pgrep -af "openai.chatgpt.*app-server" | sed 's/^/ /'
else
warn "No app-server process found."
fi
print_section "Webview cache directories"
for dir_name in "${CACHE_DIRS[@]}"; do
if [[ -e "$CFG/$dir_name" ]]; then
du -sh "$CFG/$dir_name" 2>/dev/null | sed 's/^/ /'
else
echo " missing: $dir_name"
fi
done
print_section "Result interpretation"
echo "Logs only show the backend side. The backend may be healthy while the"
echo "webview frontend is still broken."
echo
echo "To verify the actual panel:"
echo " 1. Open the Codex panel."
echo " 2. Run: Ctrl+Shift+P"
echo " 3. Select: Developer: Open Webview Developer Tools"
echo " 4. Open the Console tab."
echo
echo "Look for:"
echo " ${ASSET_HINT}-*.js Uncaught SyntaxError: Unexpected end of input"
echo
echo "If the error is gone and the chat is visible, the fix worked."
echo "If the error remains, try installing another extension version:"
echo " Extensions -> Codex/OpenAI ChatGPT -> Gear -> Install Another Version"
echo
echo "Then consider disabling extension auto-update:"
echo ' "extensions.autoUpdate": false'
}
main_mode() {
print_section "1. Is VS Code closed?"
if pgrep -x code >/dev/null; then
error "VS Code is still running. PIDs: $(pgrep -x code | tr '\n' ' ')"
echo "Cleaning webview state while VS Code is running is unreliable."
echo "Close VS Code completely and run this script again."
read -rp "Continue anyway? [y/N] " answer
case "${answer:-}" in
y|Y|yes|YES)
warn "Continuing while VS Code appears to be running."
;;
*)
echo "Aborted."
exit 1
;;
esac
else
ok "VS Code is closed."
fi
print_section "2. Codex extension on disk"
if [[ -z "$EXT" ]]; then
error "openai.chatgpt extension was not found in ~/.vscode/extensions"
else
ok "Extension directory: $EXT"
if [[ -f "$EXT/package.json" ]]; then
local version_line
version_line="$(grep -m1 '"version"' "$EXT/package.json" | tr -d ' ",')"
info "$version_line"
else
warn "package.json was not found in the extension directory."
fi
fi
print_section "3. Webview JavaScript asset check"
if [[ -n "$EXT" && -d "$EXT/webview/assets" ]]; then
local suspicious
local total
suspicious=0
total=0
for file_path in "$EXT"/webview/assets/*.js; do
[[ -e "$file_path" ]] || continue
total=$((total + 1))
local tail_text
tail_text="$(tail -c 40 "$file_path" | tr -d '\n')"
# A healthy bundle usually ends with a JavaScript terminator or
# sourceMappingURL. This is only a weak heuristic.
if ! printf '%s' "$tail_text" | grep -qE '[};)]|sourceMappingURL'; then
warn "Suspicious ending: $(basename "$file_path") ($(stat -c%s "$file_path") bytes)"
echo " tail: ${tail_text: -20}"
suspicious=$((suspicious + 1))
fi
done
info "Checked JS files: $total"
info "Suspicious JS files: $suspicious"
for file_path in "$EXT"/webview/assets/${ASSET_HINT}-*.js; do
[[ -e "$file_path" ]] || continue
local size
local parse_status
size="$(stat -c%s "$file_path")"
if command -v node >/dev/null 2>&1; then
if node --input-type=module --check < "$file_path" >/dev/null 2>&1; then
parse_status="parse OK"
else
parse_status="PARSE FAIL"
fi
else
parse_status="node not found, parse check skipped"
fi
info "$(basename "$file_path"): ${size} bytes, ${parse_status}"
done
else
warn "Webview assets directory not found."
fi
print_section "4. Webview layers before cleanup"
for dir_name in "${CACHE_DIRS[@]}" "${STATE_DIRS[@]}"; do
if [[ -e "$CFG/$dir_name" ]]; then
du -sh "$CFG/$dir_name" 2>/dev/null | sed 's/^/ /'
else
echo " missing: $dir_name"
fi
done
print_section "5a. Deleting regenerable cache directories"
for dir_name in "${CACHE_DIRS[@]}"; do
if [[ -e "$CFG/$dir_name" ]]; then
if rm -rf "$CFG/$dir_name"; then
ok "Deleted: $dir_name"
else
error "Failed to delete: $dir_name"
fi
else
info "Already missing: $dir_name"
fi
done
print_section "5b. Moving webview state directories to .bak"
for dir_name in "${STATE_DIRS[@]}"; do
if [[ -e "$CFG/$dir_name" ]]; then
rm -rf "$CFG/$dir_name.bak" 2>/dev/null
if mv "$CFG/$dir_name" "$CFG/$dir_name.bak"; then
ok "Moved to .bak: $dir_name"
else
error "Failed to move: $dir_name"
fi
else
info "Already missing: $dir_name"
fi
done
print_section "6. Webview layers after cleanup"
local clean
clean=1
for dir_name in "${CACHE_DIRS[@]}" "${STATE_DIRS[@]}"; do
if [[ -e "$CFG/$dir_name" ]]; then
error "Still exists: $dir_name"
clean=0
else
ok "Missing as expected: $dir_name"
fi
done
print_section "DONE"
if [[ "$clean" -eq 1 ]]; then
ok "All target layers were cleaned."
else
warn "Some target layers still exist. VS Code may have kept files open."
fi
echo
echo "Next steps:"
echo " 1. Open VS Code."
echo " 2. Open the Codex panel and wait 10 to 15 seconds."
echo " 3. Run:"
echo
echo " bash ~/codex_fix.sh check"
echo
echo "If the panel works, you may remove backups:"
echo
echo " rm -rf ~/.config/Code/*.bak"
echo
echo "If the cleanup made things worse, restore state directories:"
for dir_name in "${STATE_DIRS[@]}"; do
echo " rm -rf ~/.config/Code/\"$dir_name\" && mv ~/.config/Code/\"$dir_name.bak\" ~/.config/Code/\"$dir_name\""
done
}
case "${1:-}" in
check)
check_mode
;;
"")
main_mode
;;
*)
error "Unknown argument: $1"
echo "Usage:"
echo " bash ~/codex_fix.sh"
echo " bash ~/codex_fix.sh check"
exit 2
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment