{"record":{"id":"14bf266daa5f60e1","repo":"chenhg5/cc-connect","slug":"codex-app-server-exited-w","errorCode":null,"errorMessage":"codex app-server exited: %w","messagePattern":"codex app-server exited: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"agent/codex/appserver_session.go","lineNumber":1072,"sourceCode":"\tif err := scanner.Err(); err != nil && s.ctx.Err() == nil {\n\t\tslog.Debug(\"codex app-server stderr read failed\", \"error\", err)\n\t}\n}\n\nfunc (s *appServerSession) waitLoop() {\n\tdefer s.wg.Done()\n\n\ts.procMu.Lock()\n\tcmd := s.cmd\n\ts.procMu.Unlock()\n\tif cmd == nil {\n\t\treturn\n\t}\n\n\terr := cmd.Wait()\n\tif s.ctx.Err() == nil && err != nil {\n\t\tslog.Warn(\"codex app-server exited unexpectedly\", \"error\", err)\n\t\ts.emitError(fmt.Errorf(\"codex app-server exited: %w\", err))\n\t}\n\ts.alive.Store(false)\n\tif err == nil {\n\t\terr = io.EOF\n\t}\n\ts.rejectPending(err)\n}\n\nfunc (s *appServerSession) handleResponse(resp rpcResponseEnvelope) {\n\tid, ok := rpcIDToInt64(resp.ID)\n\tif !ok {\n\t\treturn\n\t}\n\n\ts.pendingMu.Lock()\n\tch := s.pending[id]\n\tdelete(s.pending, id)\n\ts.pendingMu.Unlock()","sourceCodeStart":1054,"sourceCodeEnd":1090,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/agent/codex/appserver_session.go#L1054-L1090","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read the wrapped exec error (and codex stderr) for the real exit cause","Run `codex app-server` manually with the same args to reproduce and see the startup error","Upgrade/reinstall the codex CLI to a compatible version","Check dmesg/journalctl for OOM kills and raise memory limits if needed"],"exampleFix":"// before\ncmd := exec.CommandContext(ctx, \"codex\", \"app-server\") // args drifted after codex upgrade\n// after — pin/verify the codex version at session start\nout, err := exec.Command(\"codex\", \"--version\").Output()\nif err != nil || !supportedCodexVersion(string(out)) {\n    return fmt.Errorf(\"unsupported codex binary: %s\", out)\n}","handlingStrategy":"try-catch","validationCode":"out, err := exec.Command(codexBin, \"--version\").Output()\nif err != nil {\n    return fmt.Errorf(\"codex binary not runnable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := sess.Send(ctx, prompt, nil); err != nil {\n    var eerr *exec.ExitError\n    if errors.As(err, &eerr) {\n        slog.Error(\"codex exited\", \"code\", eerr.ExitCode(), \"stderr\", stderrBuf.String())\n        sess, err = agent.StartSession(ctx, opts) // rebuild after crash\n    }\n}","preventionTips":["Pin and health-check the codex CLI version before creating sessions","Always capture the child's stderr for post-mortem on exit","Run a doctor/startup probe (`codex --version`, quick app-server handshake) before real use","Set memory limits high enough for large contexts and monitor dmesg for OOM"],"tags":["process","codex","exec","crash"],"backgroundTag":"process-exited-unexpectedly","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}