Hmbown/CodeWhale · error · anyhow::Error

runtime event stream ended before turn.completed

Error message

runtime event stream ended before turn.completed

What it means

After consuming the runtime's SSE event stream to completion, the client looks for a terminal turn.completed event. If the stream ends without one, it throws this error because a turn's outcome could not be confirmed.

Solutions

  1. Check the runtime process logs for a crash or restart during the turn.
  2. Retry the turn; transient disconnections are the most common cause.
  3. Look at proxy/gateway idle-timeout settings and raise them for long-running turns.
  4. Upgrade the runtime if it can terminate a stream without a terminal event (a known bug).
Defensive patterns

Strategy: retry

Try / catch

// Rust
match turn.wait_completed() {
    Err(e) if e.to_string().contains("ended before turn.completed") => {
        // treat as indeterminate outcome; check runtime liveness, then retry once
    }
    other => other,
}

Prevention

When it happens

Trigger: The runtime's event stream closes (EOF on the HTTP chunked response) after emitting events but before sending turn.completed — e.g. the runtime crashed, the connection dropped, or the server ended the stream early.

Common situations: Runtime process killed mid-turn (OOM, panic, deploy restart); idle connection closed by a proxy timeout; runtime bug that skips the terminal event.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/2cd399cbaaad48cd. Report an issue: GitHub.

Appendix: source

Thrown at crates/app-server/src/lib.rs:1982

                                    channel: ResponseChannel::Text,
                                });
                            }
                        }
                    }
                    "turn.completed" => {
                        let status = turn_terminal_status(&payload);
                        let error = payload
                            .pointer("/turn/error")
                            .and_then(Value::as_str)
                            .map(str::to_string);
                        return Ok((last_seq, status, error));
                    }
                    _ => {}
                }
            }
        }

        bail!("runtime event stream ended before turn.completed")
    }

    #[cfg(test)]
    fn from_base_url_for_test(base_url: String) -> Self {
        install_rustls_crypto_provider();
        Self {
            base_url,
            client: codewhale_release::platform_http_client_builder()
                .timeout(Duration::from_secs(5))
                .build()
                .expect("build reqwest test client"),
            auth_token: None,
            child: None,
            last_seq_by_thread: HashMap::new(),
        }
    }
}

View on GitHub (pinned to 73e0f67d83)