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

  1. Check that the codex CLI binary supports the app-server protocol (upgrade codex to a current version)
  2. Recreate the session via the agent's StartSession so thread/create runs and sets the session ID
  3. Log/check the thread/create response for a missing id and fix the handshake path
  4. 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

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


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/dfda9bfe093eedca. Report an issue: GitHub.