BigPizzaV3/CodexPlusPlus · error · anyhow::Error

Codex turn/start 未返回 turn id

Error message

Codex turn/start 未返回 turn id

What it means

turn/start returned a success result, but the result object contained no recognizable turn id (extract_turn_id found nothing). The library treats a turn without an id as unusable because later events cannot be correlated, so it aborts the turn immediately.

Source

Thrown at crates/codex-plus-core/src/connect/app_server.rs:158

        let mut usage = TurnUsage::default();
        let deadline = tokio::time::Instant::now() + TURN_TIMEOUT;
        while !response_received || !turn_completed {
            let remaining = deadline.saturating_duration_since(tokio::time::Instant::now());
            if remaining.is_zero() {
                bail!("等待 Codex 回复超时");
            }
            let message = self.read_message(remaining).await?;
            if is_server_request(&message) {
                self.reject_server_request(&message).await?;
                continue;
            }
            if response_id(&message) == Some(id) {
                if let Some(error) = rpc_error(&message) {
                    bail!("Codex turn/start 失败:{error}");
                }
                let result = message.get("result").cloned().unwrap_or(Value::Null);
                if extract_turn_id(&result).is_none() {
                    bail!("Codex turn/start 未返回 turn id");
                }
                if model.is_empty() {
                    model = extract_model(&result).unwrap_or_default();
                }
                if let Some(reported_usage) = extract_turn_usage(&result) {
                    usage = reported_usage;
                }
                response_received = true;
                continue;
            }

            if model.is_empty() {
                model = extract_model(&message).unwrap_or_default();
            }
            if let Some(reported_usage) = extract_turn_usage(&message) {
                usage = reported_usage;
            }

View on GitHub (pinned to f2074595a2)

Solutions

  1. Upgrade codex-plus-core to a release matched to the installed codex app-server
  2. Pin or downgrade the codex CLI to the version this crate was built against
  3. Reproduce manually against codex app-server, inspect the turn/start result JSON, and report or patch extract_turn_id
Defensive patterns

Strategy: try-catch

Try / catch

if let Err(e) = server.run_turn(&thread_id, prompt).await {
    if e.to_string().contains("未返回 turn id") {
        // protocol skew: report codex and crate versions, do not blind-retry
        return Err(e.context(format!("codex={}", codex_version())));
    }
    return Err(e);
}

Prevention

When it happens

Trigger: A codex app-server version whose turn/start result uses a different field name or shape than extract_turn_id expects; the result is Null or truncated; experimental app-server API changes.

Common situations: Version skew after upgrading the codex CLI but not codex-plus-core or vice versa; running an unstable or experimental app-server build.

Related errors


AI-assisted analysis of BigPizzaV3/CodexPlusPlus@f2074595a2 (2026-08-23). Data as JSON: /api/errors/bc2f1d4182f6435f. Report an issue: GitHub.