chenhg5/cc-connect · critical

codex app-server exited: %w

Error message

codex app-server exited: %w

What it means

After the app-server command exits, cmd.Wait() returns its exit error; if the session context was not cancelled (i.e. the exit was not an intentional shutdown) the library emits 'codex app-server exited' with the wrapped exec error. This signals an abnormal codex process termination and all pending requests are rejected.

Source

Thrown at agent/codex/appserver_session.go:1072

	if err := scanner.Err(); err != nil && s.ctx.Err() == nil {
		slog.Debug("codex app-server stderr read failed", "error", err)
	}
}

func (s *appServerSession) waitLoop() {
	defer s.wg.Done()

	s.procMu.Lock()
	cmd := s.cmd
	s.procMu.Unlock()
	if cmd == nil {
		return
	}

	err := cmd.Wait()
	if s.ctx.Err() == nil && err != nil {
		slog.Warn("codex app-server exited unexpectedly", "error", err)
		s.emitError(fmt.Errorf("codex app-server exited: %w", err))
	}
	s.alive.Store(false)
	if err == nil {
		err = io.EOF
	}
	s.rejectPending(err)
}

func (s *appServerSession) handleResponse(resp rpcResponseEnvelope) {
	id, ok := rpcIDToInt64(resp.ID)
	if !ok {
		return
	}

	s.pendingMu.Lock()
	ch := s.pending[id]
	delete(s.pending, id)
	s.pendingMu.Unlock()

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Read the wrapped exec error (and codex stderr) for the real exit cause
  2. Run `codex app-server` manually with the same args to reproduce and see the startup error
  3. Upgrade/reinstall the codex CLI to a compatible version
  4. Check dmesg/journalctl for OOM kills and raise memory limits if needed

Example fix

// before
cmd := exec.CommandContext(ctx, "codex", "app-server") // args drifted after codex upgrade
// after — pin/verify the codex version at session start
out, err := exec.Command("codex", "--version").Output()
if err != nil || !supportedCodexVersion(string(out)) {
    return fmt.Errorf("unsupported codex binary: %s", out)
}
Defensive patterns

Strategy: try-catch

Validate before calling

out, err := exec.Command(codexBin, "--version").Output()
if err != nil {
    return fmt.Errorf("codex binary not runnable: %w", err)
}

Try / catch

if err := sess.Send(ctx, prompt, nil); err != nil {
    var eerr *exec.ExitError
    if errors.As(err, &eerr) {
        slog.Error("codex exited", "code", eerr.ExitCode(), "stderr", stderrBuf.String())
        sess, err = agent.StartSession(ctx, opts) // rebuild after crash
    }
}

Prevention

When it happens

Trigger: The codex binary exits with a non-zero status while s.ctx is still active — crash, panic, bad CLI arguments, missing/broken codex installation, or OOM kill.

Common situations: Outdated or corrupted codex binary failing at startup; invalid app-server flags after a codex upgrade changed the CLI; OOM killer terminating codex on huge contexts; PATH issues resolving to a broken wrapper script.

Related errors


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