{"record":{"id":"d9fc42f265002161","repo":"xai-org/grok-build","slug":"msg-d9fc42","errorCode":null,"errorMessage":"{msg}","messagePattern":"\\{msg\\}","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-pager/src/headless.rs","lineNumber":1334,"sourceCode":"                ))\n            } else {\n                err.to_string()\n            };\n            if let Some(usage) = xai_grok_shell::sampling::error::prompt_usage_from_error(&err) {\n                match serde_json::to_value(&usage) {\n                    Ok(v) => emitter.usage = Some(v),\n                    // Log rather than swallow: a serialize failure would drop the frozen spend fields.\n                    Err(e) => tracing::warn!(\n                        error = %e,\n                        \"headless: failed to serialize prompt-error usage; spend fields dropped\"\n                    ),\n                }\n            }\n            let stop_reason_override =\n                (xai_grok_shell::sampling::error::stop_reason_for_turn_error(&err) == \"MaxTokens\")\n                    .then_some(\"max_tokens\");\n            emitter.on_error(&msg, stop_reason_override);\n            Err(anyhow::anyhow!(\"{msg}\"))\n        }\n        None => Ok(()),\n    };\n\n    // A hard stdout write error outranks the normal outcome: output is dead, so exit non-zero.\n    if let Some(err) = emitter.take_output_error() {\n        return Err(anyhow::Error::new(err).context(\"headless: stdout write failed\"));\n    }\n    outcome\n}\n\n/// Background work tracked for exit: bash/monitor tasks and background subagents, keyed by id.\n#[derive(Clone, Debug, PartialEq, Eq, Hash)]\nenum BackgroundWork {\n    Task(String),\n    Subagent(String),\n}\n","sourceCodeStart":1316,"sourceCodeEnd":1352,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-pager/src/headless.rs#L1316-L1352","documentation":"Generic terminal-error path of run_single_turn: the session channel yielded Some(Err(err)), the message is emitted via emitter.on_error (with a 'max_tokens' stop-reason override when the sampling error maps to MaxTokens), and the message is re-raised as anyhow!(\"{msg}\"). It surfaces any underlying turn failure verbatim.","triggerScenarios":"Any error terminating the turn that is not max-turns: API/network failure, sampling error like context-length/MaxTokens, provider auth rejection, tool infrastructure crash — whatever {msg} carries.","commonSituations":"Prompt exceeding the model context window (stop_reason max_tokens); expired/invalid API key; provider 5xx or rate limiting; transient network drop mid-turn.","solutions":["Read {msg} and stop_reason_override to identify the root cause","If 'max_tokens': reduce prompt size or raise the output token limit","For auth/network errors, fix credentials and retry with backoff","Enable verbose logging to capture the provider response behind msg"],"exampleFix":"// before: one blind attempt\nrun_single_turn(&mut session, &options).await?;\n// after: retry transient failures\nmatch run_single_turn(&mut session, &options).await {\n    Err(e) if is_retryable(&e) => {\n        tokio::time::sleep(Duration::from_secs(2)).await;\n        run_single_turn(&mut session, &options).await?;\n    }\n    other => other?,\n}","handlingStrategy":"retry","validationCode":"fn is_retryable(msg: &str) -> bool {\n    msg.contains(\"rate limit\") || msg.contains(\"timeout\")\n        || msg.contains(\"503\") || msg.contains(\"connection\")\n}","typeGuard":"fn is_max_tokens_error(err: &xai_grok_shell::sampling::error::Error) -> bool {\n    xai_grok_shell::sampling::error::stop_reason_for_turn_error(err) == \"MaxTokens\"\n}","tryCatchPattern":"match run_single_turn(&mut session, &options).await {\n    Err(e) if is_retryable(&e.to_string()) => {\n        tokio::time::sleep(backoff(attempt)).await;\n        retry(attempt + 1);\n    }\n    Err(e) => { emitter_on_error(&e.to_string()); std::process::exit(1); }\n    Ok(()) => {}\n}","preventionTips":["Classify the inner msg before deciding retry vs abort","Shrink prompts to stay under the context window","Handle 'max_tokens' stop reasons by raising output limits","Log provider responses to distinguish auth vs network failures"],"tags":["runtime","api","turn","rust"],"backgroundTag":"turn-runtime-error","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}