Well last night I was literally forking each chat after each finished task or was restarting VS Code so i could send the next prompt.
The reason is that there is a undefined json error (as shown in the logs)
What I did today was telling codex to do this in a new instance of vs code so it could change the javascript of codex itself without destroying its own session:
Investigate and fix the unhandled `undefined` JSON response in the Codex VS Code extension.
The issue is visible in logs as something like:
Failed to release queued message send lock
errorMessage="\"undefined\" is not valid JSON"
errorName=SyntaxError
errorStack="SyntaxError: \"undefined\" is not valid JSON
at JSON.parse (<anonymous>)
at e.onFetchResponse (.../webview/assets/app-initial-*.js:...)
..."
The goal is NOT to change queue semantics, retry turns, or work around unrelated thread behavior.
The goal is only to identify why a response reaches `JSON.parse()` as `undefined`, then fix that response boundary safely and minimally.
Use the following investigation approach.
1. Locate the installed extension
On Linux it is typically under:
~/.vscode/extensions/
Find the Codex extension:
find ~/.vscode/extensions -maxdepth 1 -type d -iname 'openai.chatgpt-*'
Enter the installed extension directory:
cd ~/.vscode/extensions/openai.chatgpt-<version>-linux-x64
2. Inspect the extension structure
Check the manifest:
cat package.json
The main VS Code extension entry point should look similar to:
"main": "./out/extension.js"
List the webview assets:
find webview -type f | sort | head -100
Inspect the webview entry point:
cat webview/index.html
List the larger application bundles:
ls -lh webview/assets/app-initial-*.js
3. Locate the relevant queue/IPC code
Search the extension host bundle:
grep -oE \
'queued-followups|queued-follow-ups|thread-queued-followups-changed|thread-stream-state-changed|thread-follower-set-queued-follow-ups-state|thread-follower-remove-queued-message|thread-follower-clear-queued-messages' \
out/extension.js | sort | uniq -c
Find the corresponding webview bundles:
grep -RIl \
-E 'thread-follower-set-queued-follow-ups-state|thread-follower-remove-queued-message|thread-follower-clear-queued-messages|thread-queued-followups-changed' \
webview/assets
Also locate the setting-related bundle if useful:
grep -RIl 'followUpQueueMode' \
webview/assets/app-initial-*.js \
webview/assets/general-settings-*.js \
webview/assets/user-message-*.js
4. Locate the failing response parser
Search all app bundles for the response handler:
grep -RIl 'onFetchResponse' webview/assets/app-initial-*.js
Then extract context without pretty-printing the entire minified bundle:
python3 - <<'PY'
from pathlib import Path
for p in Path("webview/assets").glob("app-initial-*.js"):
s = p.read_text(errors="replace")
for term in [
"onFetchResponse",
"Failed to release queued message send lock",
"JSON.parse",
]:
pos = 0
while True:
i = s.find(term, pos)
if i < 0:
break
print("\n" + "#" * 100)
print(p)
print(term, "@", i)
print("#" * 100)
print(s[max(0, i - 2500):i + 5000])
pos = i + len(term)
PY
If the stack trace contains an exact minified line/column, extract that area directly.
For example, for line 3 column 1518:
python3 - <<'PY'
from pathlib import Path
p = Path("webview/assets/app-initial-48c569ae16a4.js")
lines = p.read_text(errors="replace").splitlines()
line_number = 3
column = 1518
line = lines[line_number - 1]
print(line[max(0, column - 1200):column + 1800])
PY
5. Trace the producer and consumer
Do not only patch `JSON.parse()` blindly.
Determine the full response path:
queued-message lock release
-> request
-> VS Code/webview bridge
-> request handler
-> handler return value
-> serialization
-> response delivery
-> onFetchResponse
-> JSON.parse
Specifically determine:
- whether the response value is JavaScript `undefined`
- whether it is the literal string `"undefined"`
- whether the handler intentionally returns no value
- whether `JSON.stringify(undefined)` is involved
- whether an empty/void response is valid for this request
- whether another layer expects a specific JSON response shape
Search for useful related strings:
grep -Rni \
-E 'onFetchResponse|queued message send lock|JSON.stringify|JSON.parse|fetch-response|fetchResponse' \
webview/assets out \
2>/dev/null
6. Fix the narrowest correct boundary
Preferred fix if the producer is serializing a void result:
Instead of:
JSON.stringify(result)
normalize only the void response:
JSON.stringify(result ?? null)
because:
JSON.stringify(undefined) === undefined
JSON.stringify(null) === "null"
If an empty response is explicitly valid and the producer cannot safely be changed, make the specific response parser tolerate only empty/void responses.
Conceptually:
const parsed =
value === undefined ||
value === null ||
value === "" ||
value === "undefined"
? null
: JSON.parse(value);
Do NOT globally replace or wrap every `JSON.parse()` call.
Do NOT return an invented payload such as:
{ "success": true }
unless the existing protocol clearly specifies that schema.
Do NOT add retries unless investigation proves that the response is temporarily unavailable and a later retry returns valid data.
If the handler deliberately returns void, retrying it will simply return `undefined` again.
7. Back up the bundle before modifying it
For example:
cp \
webview/assets/app-initial-48c569ae16a4.js \
webview/assets/app-initial-48c569ae16a4.js.bak
If another bundle is modified, back that one up separately as well.
8. Keep the patch minimal
The bundles are minified, so avoid reformatting or rewriting the entire file.
Prefer an exact replacement with a script that first verifies that the target fragment occurs exactly once.
Example workflow:
python3 - <<'PY'
from pathlib import Path
p = Path("webview/assets/app-initial-48c569ae16a4.js")
s = p.read_text()
old = 'EXACT_ORIGINAL_FRAGMENT'
new = 'EXACT_PATCHED_FRAGMENT'
count = s.count(old)
print("matches:", count)
if count != 1:
raise SystemExit("Refusing to patch: expected exactly one match")
p.write_text(s.replace(old, new, 1))
PY
9. Validate the modified bundle
If possible:
node --check webview/assets/app-initial-48c569ae16a4.js
Compare against the backup:
cmp \
webview/assets/app-initial-48c569ae16a4.js.bak \
webview/assets/app-initial-48c569ae16a4.js
For a minified single-line file, inspect only the modified region rather than producing a huge full-file diff.
10. Reload VS Code and reproduce
Use:
Developer: Reload Window
Then reproduce the operation that previously caused:
Failed to release queued message send lock
"undefined" is not valid JSON
Check the latest Codex extension logs:
grep -Rni \
-E 'Failed to release queued message send lock|undefined.*valid JSON' \
~/.config/Code/logs \
2>/dev/null | tail -100
The fix is successful if the invalid JSON exception no longer occurs and the relevant operation still completes normally.
11. Report the actual root cause
Document:
- extension version
- affected bundle
- affected function
- exact producer of the `undefined` response
- exact consumer that called `JSON.parse`
- whether the value was JS `undefined` or the string `"undefined"`
- whether the handler intentionally returned void
- the minimal patch
- why `null` is the correct representation, if applicable
- verification steps
- confirmation that no broad JSON parsing behavior was changed
A concise root-cause description should look roughly like this:
"The VS Code webview response bridge unconditionally attempted to JSON.parse a response from a handler that can legitimately return no value. A void JavaScript result was therefore propagated as `undefined`, which is not valid JSON. Normalizing void responses to JSON `null` at the serialization boundary (or explicitly accepting an empty response in this one consumer) prevents the SyntaxError without changing unrelated queue or thread behavior."
Do not investigate or modify unrelated duplicate-turn, replay, model-selection, or queue-ordering behavior as part of this fix.
codex needed roughly 15 minutes to monkey patch it - (it runs on my machine)
I have also reported it to github in hope that it will not be overriden by the next update with the bug still in the code.
So this post is firstly meant as a tip for the guys who have the same problem (you are not helpless - you can fix codex yourself sometimes - let it analyse the problem itself)
And of course secondly just in case someone at OpenAI - if you see this. Please add the fix to the next update.
It was a horrible night!
version 26.5928.31416 and the pre release both have that error
Linux 6.8.0-142-generic x86_64 x86_64
It was also having the error after restart - reload of the extension or the window and after changing the model from 6.1-sol to gpt-6-sol

