github/copilot-sdk · error
failed to write a frame to the in-process runtime connection
Error message
failed to write a frame to the in-process runtime connection
What it means
This AsyncWrite impl for the in-process runtime connection returns a BrokenPipe io::Error when shared.write_frame(buf) reports the frame could not be queued — i.e. the runtime side of the in-process channel is gone (receiver dropped or shut down). The error surfaces to Tokio-based writers as a failed write on the connection, which typically tears the connection down with a BrokenPipe classification.
Solutions
- Ensure the runtime is alive before writing: keep the runtime handle/join guard alive for the connection's lifetime and shut down clients first, runtime last.
- Treat the BrokenPipe error as terminal: recreate the client/connection (restart the runtime) rather than retrying the same connection.
- Drain in-flight requests and close connections gracefully before dropping/shutting down the runtime side.
- Check application logs for a runtime-side panic or early exit that dropped the receiver unexpectedly.
Example fix
// before let conn = Connection::in_process(&runtime); spawn(worker(conn.clone())); drop(runtime); // receiver gone; next write -> BrokenPipe // after let conn = Connection::in_process(&runtime); let worker = spawn(worker(conn.clone())); worker.await?; // drain requests first drop(conn); drop(runtime);
Defensive patterns
Strategy: try-catch
Validate before calling
// Rust: check the runtime is still running before writing
fn connection_usable(runtime: &RuntimeHandle) -> bool { runtime.is_running() } Type guard
fn is_connected(conn: &Connection) -> bool { !conn.is_closed() } Try / catch
match conn.send_frame(&buf).await {
Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => {
// receiver dropped: recreate runtime connection and retry once
let conn = reconnect()?;
conn.send_frame(&buf).await?;
}
other => other?,
} Prevention
- Keep the runtime handle alive for as long as any connection exists (own it in a long-lived struct).
- Shut down in order: clients/connections first, runtime last; await in-flight tasks before dropping the runtime.
- Map BrokenPipe to a reconnect path instead of retrying on the same connection.
- Investigate runtime-side panics that silently drop the receiver.
When it happens
Trigger: Writing to the in-process runtime connection after the runtime task/handle has been dropped or shut down; issuing requests concurrently with runtime shutdown; poll_write invoked on a connection whose shared state already closed its receiver.
Common situations: Shutting down the embedded runtime while requests are still in flight; holding a client/connection across a runtime restart; a panic or early return in the runtime loop dropping the receiver while the caller keeps sending frames.
Related errors
- writer actor has shut down
- writer actor dropped ack without responding
- runtime.shutdown timed out during Client::stop
- Cannot log after the factory run has settled
- Request cancelled by runtime
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/7737c07b783adfb2.
Report an issue: GitHub.
Appendix: source
Thrown at rust/src/ffi.rs:190
}
}
/// Write side of the FFI transport. Each frame is forwarded synchronously to
/// the native `connection_write` export (native copies before returning).
pub(crate) struct FfiWriter {
shared: Arc<FfiShared>,
}
impl AsyncWrite for FfiWriter {
fn poll_write(
self: Pin<&mut Self>,
_cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<std::io::Result<usize>> {
if self.shared.write_frame(buf) {
Poll::Ready(Ok(buf.len()))
} else {
Poll::Ready(Err(std::io::Error::new(
std::io::ErrorKind::BrokenPipe,
"failed to write a frame to the in-process runtime connection",
)))
}
}
fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
Poll::Ready(Ok(()))
}
fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
Poll::Ready(Ok(()))
}
}
/// Prepared FFI host. The cdylib is loaded process-globally and never unloaded
/// (see [`load_library`]).
pub(crate) struct FfiHost {View on GitHub (pinned to cd8cf15dc3)