chenhg5/cc-connect · error
codex app-server thread id is empty
Error message
codex app-server thread id is empty
What it means
The codex app-server session attempted to start a turn but the session has no thread ID (CurrentSessionID() returned an empty string). The thread ID is established when the app-server thread is created/resumed; sending input without it means the session was never initialized, so the library fails fast instead of sending an unusable turn/start request.
Source
Thrown at agent/codex/appserver_session.go:468
filePaths := core.SaveFilesToDisk(s.workDir, messageID, files)
prompt = core.AppendFileRefs(prompt, filePaths)
}
prompt, imagePaths, err := s.stageImages(prompt, images)
if err != nil {
return err
}
s.stateMu.Lock()
if !s.preambleSent {
prompt = prependCodexPromptPreamble(prompt, s.promptPreamble)
s.preambleSent = true
}
s.stateMu.Unlock()
threadID := s.CurrentSessionID()
if threadID == "" {
return fmt.Errorf("codex app-server thread id is empty")
}
input := make([]map[string]any, 0, 1+len(imagePaths))
input = append(input, map[string]any{
"type": "text",
"text": prompt,
"text_elements": []any{},
})
for _, path := range imagePaths {
input = append(input, map[string]any{
"type": "localImage",
"path": path,
})
}
params := map[string]any{
"threadId": threadID,
"input": input,View on GitHub (pinned to 4000b2338a)
Solutions
- Check that the codex CLI binary supports the app-server protocol (upgrade codex to a current version)
- Recreate the session via the agent's StartSession so thread/create runs and sets the session ID
- Log/check the thread/create response for a missing id and fix the handshake path
- Verify no code path resets s.currentSessionID to empty after initialization
Example fix
// before
s := &appServerSession{} // never went through thread/create
s.Send(ctx, prompt, nil)
// after
sess, err := agent.StartSession(ctx, sessionOpts) // performs thread/create and sets the thread id
if err != nil { return err }
sess.Send(ctx, prompt, nil) Defensive patterns
Strategy: validation
Validate before calling
if sess == nil || sess.CurrentSessionID() == "" {
return fmt.Errorf("session not initialized: no thread id")
}
sess.Send(ctx, prompt, nil) Prevention
- Always create sessions via agent.StartSession, never by constructing the session type directly
- Check IsAlive()/session state before sending after long idle periods
- Log the thread id at session start so empty-id states are caught early
When it happens
Trigger: Calling Send (or SendWithImages) on an appServerSession whose thread/create or thread/resume handshake never completed or failed silently, so s.currentSessionID was never populated.
Common situations: Starting a session against an older codex binary that does not support app-server thread creation; the thread/create response was malformed; manually constructing an appServerSession instead of going through the agent's StartSession; a race where Send is called before the session finished initializing.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- codex app-server turn/start: %w
- codex app-server turn/start returned empty turn id
- turn failed (no details)
- %s
- codex app-server connection is closed
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/dfda9bfe093eedca.
Report an issue: GitHub.