1
00:00:00,000 --> 00:00:05,440
Thanks to Jellypod to help make this daily
show a reality, today we're talking about

2
00:00:05,520 --> 00:00:11,440
a particularly frustrating issue hitting
Windows developers using the Codex CLI.

3
00:00:11,573 --> 00:00:17,600
It's a silent hang where the CLI just sits
there indefinitely showing a "Working"

4
00:00:17,680 --> 00:00:21,120
status right after a local PowerShell tool
call completes.

5
00:00:21,328 --> 00:00:25,120
Maya, you actually ran into this first
hand during a launch prep,

6
00:00:25,152 --> 00:00:25,600
didn't you?

7
00:00:26,440 --> 00:00:27,819
Oh, absolutely.

8
00:00:28,980 --> 00:00:33,859
I was running a simple ripgrep search
through PowerShell using `rg` to find some

9
00:00:33,879 --> 00:00:35,479
configuration strings.

10
00:00:35,539 --> 00:00:39,199
The tool finished instantly, returned the
correct results to my terminal,

11
00:00:39,840 --> 00:00:40,279
and then...

12
00:00:41,299 --> 00:00:41,699
nothing.

13
00:00:42,459 --> 00:00:47,079
Codex just sat there, spinning on
"Working," consuming zero CPU,

14
00:00:47,199 --> 00:00:49,600
but completely unresponsive.

15
00:00:49,719 --> 00:00:52,139
I had to manually kill the terminal
process.

16
00:00:53,000 --> 00:00:56,440
And the reason this happens is
surprisingly low-level.

17
00:00:56,653 --> 00:01:00,400
It's not a network drop or an API rate
limit.

18
00:01:00,520 --> 00:01:05,640
It comes down to manual string
interpolation inside the CLI's transcript

19
00:01:05,709 --> 00:01:06,680
serialization.

20
00:01:06,810 --> 00:01:12,760
Instead of passing the tool's output to a
robust, safe JSON serializer,

21
00:01:12,800 --> 00:01:17,560
the engine was manually concatenating
strings to write the local session history

22
00:01:17,688 --> 00:01:21,240
into a JSONL, or JSON Lines, file.

23
00:01:22,459 --> 00:01:26,039
Wait, manual string concatenation for
JSON?

24
00:01:26,519 --> 00:01:29,179
That's Web dev 101 of what not to do.

25
00:01:29,759 --> 00:01:34,100
If the tool output contains unescaped
double quotes or non-ASCII characters,

26
00:01:34,460 --> 00:01:36,759
the entire JSON structure breaks down.

27
00:01:38,000 --> 00:01:38,920
Exactly.

28
00:01:39,013 --> 00:01:43,280
In this case, ripgrep returned code
snippets containing double quotes,

29
00:01:43,320 --> 00:01:48,720
and PowerShell piped them out using its
default non-UTF-8 encoding,

30
00:01:48,764 --> 00:01:50,160
creating Mojibake.

31
00:01:50,300 --> 00:01:56,000
The serializer wrote raw, unescaped quotes
directly into the `function_call_output`

32
00:01:56,053 --> 00:01:58,400
field of that JSONL line.

33
00:01:58,480 --> 00:02:03,840
That means you end up with a malformed
JSON line in your local session transcript.

34
00:02:04,419 --> 00:02:07,539
Right, so the file on disk is corrupted.

35
00:02:08,019 --> 00:02:14,399
But why does a local malformed JSON file
cause the active HTTPS connection to hang?

36
00:02:14,979 --> 00:02:18,559
You'd think the local CLI would just crash
with a JSON parse error.

37
00:02:19,000 --> 00:02:20,120
You would think so!

38
00:02:20,280 --> 00:02:22,760
But here is the sequence of events.

39
00:02:22,872 --> 00:02:26,840
When Codex prepares to send the next
interaction to the server,

40
00:02:26,920 --> 00:02:31,400
it reads the local JSONL file to
reconstruct the conversation history.

41
00:02:31,613 --> 00:02:36,520
It parses the lines, hits the malformed
`function_call_output` block,

42
00:02:36,640 --> 00:02:39,160
and fails silently or partially.

43
00:02:39,336 --> 00:02:44,440
Then, it initiates a `responses_http` POST
request to

44
00:02:44,480 --> 00:02:49,000
`chatgpt.com/responses` to send the state
payload.

45
00:02:49,500 --> 00:02:55,639
Ah, so the payload itself is corrupted or
incomplete, and because of how the API

46
00:02:55,679 --> 00:03:00,759
client is configured, it sends a bad
request body but keeps the connection open,

47
00:03:01,259 --> 00:03:04,199
waiting for a response that the server is
never going to send.

48
00:03:05,000 --> 00:03:06,080
Spot on.

49
00:03:06,150 --> 00:03:10,440
The connection stays wide open, the socket
doesn't time out,

50
00:03:10,480 --> 00:03:14,920
and because there's no client-side timeout
handling that specific state,

51
00:03:14,940 --> 00:03:17,880
the user is left looking at "Working"
forever.

52
00:03:18,379 --> 00:03:23,879
Okay, so if we are stuck in this state
right now, how do we actually find where the

53
00:03:23,940 --> 00:03:24,699
corruption is?

54
00:03:25,279 --> 00:03:28,420
Where is this JSONL file stored, and what
are we looking for?

55
00:03:29,000 --> 00:03:31,800
You need to look in your local Codex state
directory.

56
00:03:31,900 --> 00:03:37,480
The session transcripts are typically
stored as `.jsonl` files named after your

57
00:03:37,549 --> 00:03:38,920
active thread ID.

58
00:03:39,080 --> 00:03:44,120
Open that file in a proper text editor,
and look at the very last line.

59
00:03:44,360 --> 00:03:49,720
If you see unescaped quotes inside the
`function_call_output` JSON block,

60
00:03:49,747 --> 00:03:54,680
or blocky Mojibake characters where UTF-8
characters should be,

61
00:03:54,720 --> 00:03:55,800
you've found the culprit.

62
00:03:56,779 --> 00:04:00,819
So to recover immediately, can we just
delete that corrupted line,

63
00:04:00,900 --> 00:04:02,579
or do we have to wipe the whole session?

64
00:04:03,000 --> 00:04:04,440
You have two choices.

65
00:04:04,547 --> 00:04:09,320
If you want to save the session, you can
open the file, delete the corrupted line

66
00:04:09,391 --> 00:04:13,720
entirely, or truncate the file to the last
known-good turn,

67
00:04:13,760 --> 00:04:14,440
and save it.

68
00:04:14,653 --> 00:04:19,320
If you don't care about the history, the
easiest path is to just start a clean

69
00:04:19,389 --> 00:04:22,920
thread using `codex --new-thread`.

70
00:04:23,659 --> 00:04:28,440
That's a good quick fix, but we need to
stop it from happening again the next time a

71
00:04:28,480 --> 00:04:31,479
tool returns a non-ASCII character or a
quote.

72
00:04:32,159 --> 00:04:34,960
How do we fix the PowerShell encoding side
of things?

73
00:04:36,000 --> 00:04:38,720
This is the crucial step for Windows
users.

74
00:04:38,793 --> 00:04:44,720
PowerShell's default output encoding is
often set to regional ANSI code pages,

75
00:04:44,768 --> 00:04:47,360
like Windows-1252.

76
00:04:47,520 --> 00:04:52,400
To force UTF-8, you need to configure your
PowerShell profile.

77
00:04:52,540 --> 00:04:57,520
Run these two commands to force UTF-8
globally for your session:

78
00:04:57,680 --> 00:05:00,400
`$OutputEncoding =

79
00:05:00,400 --> 00:05:06,720
[System.Text.Encoding]::UTF8` and

80
00:05:06,720 --> 00:05:10,800
`[Console]::OutputEncoding =

81
00:05:11,040 --> 00:05:16,080
[System.Text.Encoding]::UTF8`.

82
00:05:17,379 --> 00:05:22,440
Putting those two lines into your
`$PROFILE` script is basically mandatory if you're

83
00:05:22,460 --> 00:05:24,579
running local tools with Codex on Windows.

84
00:05:25,159 --> 00:05:29,859
It ensures that when tools like `rg` or
`dir` write to stdout,

85
00:05:30,319 --> 00:05:35,420
PowerShell doesn't transform high-ASCII
characters into garbage that breaks the

86
00:05:35,459 --> 00:05:36,579
transcript serializer.

87
00:05:37,000 --> 00:05:38,040
Exactly.

88
00:05:38,120 --> 00:05:40,280
And on the build side, there's good news.

89
00:05:40,467 --> 00:05:47,400
If you upgrade to the latest
`0.142.0-alpha` release, they've started addressing

90
00:05:47,440 --> 00:05:49,640
these serialization bottlenecks.

91
00:05:49,656 --> 00:05:54,680
They've also updated their environment
setup, moving to `uv sync` for managing the

92
00:05:54,760 --> 00:06:00,040
Python SDK dependencies, which makes local
environment rebuilds much faster and

93
00:06:00,090 --> 00:06:00,520
cleaner.

94
00:06:01,379 --> 00:06:06,279
That `uv sync` addition is huge for
keeping the Python environment stable.

95
00:06:06,319 --> 00:06:12,920
So, update to `0.142.0-alpha`, force UTF-8
in your PowerShell profile,

96
00:06:13,359 --> 00:06:16,979
and if you get a silent hang, check your
local `.jsonl` file.

97
00:06:18,000 --> 00:06:18,880
That's the playbook.

98
00:06:18,983 --> 00:06:22,000
Thanks for listening, and we'll catch you
on the next one.

