{"record":{"id":"fe516e8c16e2aa0c","repo":"chenhg5/cc-connect","slug":"turn-failed-no-details","errorCode":null,"errorMessage":"turn failed (no details)","messagePattern":"turn failed \\(no details\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agent/codex/appserver_session.go","lineNumber":1137,"sourceCode":"\n\tcase \"item/completed\":\n\t\tvar notif itemNotification\n\t\tif err := json.Unmarshal(paramsRaw, &notif); err == nil {\n\t\t\ts.handleItemCompleted(notif.Item)\n\t\t}\n\n\tcase \"turn/completed\":\n\t\tvar notif turnNotification\n\t\tif err := json.Unmarshal(paramsRaw, &notif); err == nil {\n\t\t\tif strings.EqualFold(strings.TrimSpace(notif.Turn.Status), \"failed\") || notif.Turn.Error != nil {\n\t\t\t\terrMsg := \"\"\n\t\t\t\tif notif.Turn.Error != nil {\n\t\t\t\t\terrMsg = strings.TrimSpace(notif.Turn.Error.Message)\n\t\t\t\t}\n\t\t\t\tif errMsg == \"\" {\n\t\t\t\t\terrMsg = \"turn failed (no details)\"\n\t\t\t\t}\n\t\t\t\ts.failTurn(fmt.Errorf(\"%s\", errMsg))\n\t\t\t} else {\n\t\t\t\ts.completeTurn()\n\t\t\t}\n\t\t}\n\n\tcase \"thread/status/changed\":\n\t\tvar notif struct {\n\t\t\tThreadID string `json:\"threadId\"`\n\t\t\tStatus   struct {\n\t\t\t\tType string `json:\"type\"`\n\t\t\t} `json:\"status\"`\n\t\t}\n\t\tif err := json.Unmarshal(paramsRaw, &notif); err == nil && notif.Status.Type == \"idle\" {\n\t\t\t// In codex 0.125+, thread going idle signals turn completion.\n\t\t\ts.completeTurn()\n\t\t}\n\n\tcase \"account/rateLimits/updated\":","sourceCodeStart":1119,"sourceCodeEnd":1155,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/agent/codex/appserver_session.go#L1119-L1155","documentation":"Raised by the codex app-server session when a `turn/completed` notification arrives with status \"failed\" (or an error object) but the error payload carries no usable message text. The adapter cannot report a cause, so it substitutes the placeholder \"turn failed (no details)\" and fails the pending turn via failTurn. It means the codex app-server aborted the turn without explaining why.","triggerScenarios":"The `turn/completed` JSON-RPC notification is received where `notif.Turn.Status` equals \"failed\" (case-insensitive) or `notif.Turn.Error` is non-nil, AND `notif.Turn.Error.Message` is empty or whitespace-only.","commonSituations":"Codex app-server crashes or hits an internal error mid-turn without populating the error message; protocol version drift (codex 0.125+) where the error schema changed and the message field moved or was renamed; overloaded backend returning bare failure status; malformed turn error payloads after proxying.","solutions":["Run the codex CLI directly on the same prompt to see the underlying failure (auth expired, model unavailable, quota exhausted).","Check codex CLI version and upgrade both the codex binary and cc-connect so the error schema matches (`codex --version`).","Verify codex authentication (`codex login`) and API quota; silent failures often mean expired credentials.","Inspect the codex app-server's own logs/stderr for the real error text that was not carried in the notification.","Retry the turn; transient backend failures often surface as bare failed status."],"exampleFix":"// before: error text missing, no way to see why\nerrMsg := \"turn failed (no details)\"\n\n// after: log the raw notification for debugging\nif notif.Turn.Error != nil {\n    errMsg = strings.TrimSpace(notif.Turn.Error.Message)\n}\nif errMsg == \"\" {\n    slog.Warn(\"codex turn failed without error details\", \"status\", notif.Turn.Status)\n    errMsg = \"turn failed (no details)\"\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// consume session events\nfor ev := range sess.Events() {\n    if ev.Type == core.EventError {\n        if strings.Contains(ev.Error.Error(), \"no details\") {\n            slog.Warn(\"codex turn failed without cause; check codex CLI logs\")\n        }\n        // surface to user or retry\n    }\n}","preventionTips":["Keep codex CLI and cc-connect versions in sync.","Verify codex auth (`codex login`) before long sessions.","Monitor codex stderr for the real failure text.","Retry failed turns once before surfacing to the user."],"tags":["codex","app-server","json-rpc","agent-session"],"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"}