{"record":{"id":"130fcb4cc803907e","repo":"chenhg5/cc-connect","slug":"s-130fcb","errorCode":null,"errorMessage":"%s","messagePattern":"%s","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agent/pi/session.go","lineNumber":430,"sourceCode":"\t\t}\n\t\ts.handleEvent(raw)\n\t}\n\n\terr = cmd.Wait()\n\tif err != nil {\n\t\tslog.Error(\"piSession: process error\", \"cmd\", s.cmd, \"error\", err, \"stderr\", stderrBuf.String())\n\t\tevt := core.Event{Type: core.EventError, Error: fmt.Errorf(\"pi: %s: %w\", strings.TrimSpace(stderrBuf.String()), err)}\n\t\tselect {\n\t\tcase s.events <- evt:\n\t\tcase <-s.ctx.Done():\n\t\t}\n\t}\n\n\t// Signal turn completion. Flush a deferred terminal error first in\n\t// case the process exited without a final non-retry agent_end (the\n\t// agent_end handler normally flushes pendingErr already).\n\tif s.pendingErr != \"\" {\n\t\terrEvt := core.Event{Type: core.EventError, Error: fmt.Errorf(\"%s\", s.pendingErr)}\n\t\ts.pendingErr = \"\"\n\t\tselect {\n\t\tcase s.events <- errEvt:\n\t\tcase <-s.ctx.Done():\n\t\t}\n\t}\n\tsid := s.CurrentSessionID()\n\tevt := core.Event{Type: core.EventResult, SessionID: sid, Done: true}\n\tselect {\n\tcase s.events <- evt:\n\tcase <-s.ctx.Done():\n\t}\n\n\treturn nil\n}\n\n// writeRPCCommand marshals cmd as a single JSONL line and writes it to the\n// RPC process's stdin under rpcStdinMu. Used by both sendRPC (for \"prompt\"","sourceCodeStart":412,"sourceCodeEnd":448,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/agent/pi/session.go#L412-L448","documentation":"agent/pi/session.go:430 — after a JSON-mode turn completes, sendJSON flushes any deferred terminal error stored in s.pendingErr as core.Event{Type:EventError, Error:fmt.Errorf(\"%s\", s.pendingErr)}. pendingErr is set by handleEvent (e.g. a non-retryable agent error that didn't end with a failed agent_end); this flush covers the case where the process exited without a final agent_end to flush it normally.","triggerScenarios":"sendJSON (via Send, non-rpc mode) when handleEvent recorded s.pendingErr during the turn: (1) pi reported a fatal, non-retryable agent error event; (2) the process exited before emitting a terminal agent_end that would normally clear it; (3) a provider refused the request with a terminal status pi surfaced as pending error text.","commonSituations":"Provider auth/quota failures mid-turn; pi aborting on an invalid tool call; context-window overflow errors from the model; prompt rejected by the provider (e.g. oversized inlined content).","solutions":["Read the pendingErr text in the event — it is pi's terminal error message; address what it describes (auth, quota, prompt size).","Retry the prompt if the cause was transient (rate limit, network).","Shorten the prompt or move large content into on-disk files referenced by path rather than inlined.","Check pi logs/version if the message indicates an internal pi error and upgrade."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":"func isPendingErrFlush(evt core.Event) bool {\n    return evt.Type == core.EventError && evt.Error != nil &&\n        !strings.HasPrefix(evt.Error.Error(), \"pi: \") &&\n        !strings.HasPrefix(evt.Error.Error(), \"read stdout:\")\n}","tryCatchPattern":"sawResult := false\nfor evt := range session.Events() {\n    if evt.Type == core.EventResult && evt.Done { sawResult = true }\n    if evt.Type == core.EventError && evt.Error != nil {\n        slog.Warn(\"pi terminal agent error\", \"msg\", evt.Error.Error())\n    }\n}\nif !sawResult { // turn ended via pendingErr flush, not agent_end\n    offerRetryToUser()\n}","preventionTips":["Treat EventError without a following Done result as a failed turn and offer a retry.","Keep provider credentials and quota healthy to avoid terminal agent errors.","Shorten prompts and reference large files by path to avoid provider rejections.","Log pendingErr text verbatim for diagnosis; it names pi's failure reason."],"tags":["agent-error","event-stream","deferred-error","go","agent-pi"],"backgroundTag":"upstream-api-error","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}