chenhg5/cc-connect · critical
codex app-server connection closed
Error message
codex app-server connection closed: %w
What it means
The reader goroutine's scan failed for a reason other than the line-size limit while the session context was still live — the app-server's stdout closed unexpectedly. The library logs the read failure, emits this wrapped error, marks the session dead, and rejects all pending requests and approvals with the same error.
Solutions
- Check codex stderr and system logs (journalctl, dmesg for OOM) for the crash cause
- Restart the session/agent after the process dies — this error is terminal for the session
- Verify codex isn't being killed by resource limits (memory, cgroup)
- Look at the wrapped cause for the actual OS error and fix accordingly (EPIPE → process death)
Example fix
// before
err := sess.Send(ctx, prompt, nil) // fails after process death, session unusable
// after
if err != nil && !sess.IsAlive() {
slog.Warn("codex session died, restarting", "err", err)
sess, err = agent.StartSession(ctx, opts)
} Defensive patterns
Strategy: retry
Validate before calling
if !sess.IsAlive() {
sess, err = agent.StartSession(ctx, opts)
if err != nil { return fmt.Errorf("codex session dead and restart failed: %w", err)
} } Try / catch
if err := sess.Send(ctx, prompt, nil); err != nil {
if !sess.IsAlive() { // connection closed by dead process
if s2, rerr := agent.StartSession(ctx, opts); rerr == nil {
return s2.Send(ctx, prompt, nil)
}
}
return err
} Prevention
- Monitor codex memory usage; raise limits to avoid OOM kills
- Capture stderr to a log file so crash causes are diagnosable
- Watch session Events() for terminal errors and auto-restart the session
- Keep codex updated; crashes often come from fixed bugs
When it happens
Trigger: The codex process dies or closes its stdout pipe mid-session so scanner returns a non-EOF, non-ErrTooLong error (e.g. EPIPE) before s.ctx is cancelled.
Common situations: OOM-killer or crash terminating codex mid-turn; user kills the codex process; pipe broken when the parent reaps the process; container restart; a codex panic writing to stderr and exiting hard.
Understand the failure class
- Connection failures: ECONNREFUSED, ECONNRESET, and friends — why connections get refused, reset, or dropped.
Related errors
- codex app-server exited
- codex app-server turn/start
- read stdout
- write timed out
- another cc-connect instance is already running
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/8ddee67a24eed1f8.
Report an issue: GitHub.
Appendix: source
Thrown at agent/codex/appserver_session.go:1028
default:
// Notification (no id).
var notif rpcNotificationEnvelope
if err := json.Unmarshal(data, ¬if); err != nil {
slog.Debug("codex app-server: bad notification envelope", "error", err)
continue
}
s.handleNotification(notif.Method, notif.Params)
}
}
err := scanner.Err()
if err != nil {
if s.ctx.Err() == nil && !errors.Is(err, io.EOF) {
slog.Warn("codex app-server read failed", "error", err)
if errors.Is(err, bufio.ErrTooLong) {
s.emitError(fmt.Errorf("codex app-server line exceeds max size (%d bytes): %w", maxLineSize, err))
} else {
s.emitError(fmt.Errorf("codex app-server connection closed: %w", err))
}
}
s.alive.Store(false)
s.rejectPending(err)
s.rejectPendingApprovals(err)
return
}
s.alive.Store(false)
s.rejectPending(io.EOF)
s.rejectPendingApprovals(io.EOF)
}
func (s *appServerSession) stderrLoop(r io.Reader) {
defer s.wg.Done()
scanner := bufio.NewScanner(r)
buf := make([]byte, 0, 64*1024)
scanner.Buffer(buf, 1024*1024)View on GitHub (pinned to 4000b2338a)