github/copilot-sdk · error
Failed to write a frame to the in-process runtime…
Error message
Failed to write a frame to the in-process runtime connection.
What it means
The native connectionWrite call returned false, meaning the FFI layer could not deliver the frame buffer to the in-process runtime. Unlike error 80 the connection is nominally open, but the underlying write failed — typically because the runtime process/pipe is dead or backpressured beyond recovery. Thrown from writeFrame during the constructor's handshake write.
Solutions
- Reinstall the SDK so the correct platform runtime.node is present (see runtime bundle validation errors).
- Check the runtime process logs/stderr for a crash right before the write failure.
- Retry session creation — a transient runtime startup failure can produce a one-off write failure.
- Confirm the runtime bundle version matches the SDK version (mixed installs cause protocol/ABI mismatch).
Example fix
// before
const { runtimePath } = ensureRuntimeBundle({});
const host = new FfiRuntimeHost(loadLib(runtimePath)); // runtime node from an old install
// after
// reinstall @github/copilot-sdk and its platform package so versions match
npm install @github/copilot-sdk Defensive patterns
Strategy: retry
Validate before calling
if (!existsSync(runtimePath)) throw new Error('runtime binary missing before connect'); Try / catch
try {
host = new FfiRuntimeHost(lib);
} catch (e) {
if (e.message.includes('Failed to write a frame')) {
// transient native failure: rebuild lib+host with backoff
await sleep(RETRY_MS);
host = createHost();
} else throw e;
} Prevention
- Keep SDK and platform runtime package versions in lockstep.
- Verify runtime.node integrity after install (non-zero size).
- Monitor runtime process health/stderr for early crashes.
When it happens
Trigger: this.lib.connectionWrite(connectionId, frame, length) returns false for the initial handshake frame: the native runtime died at startup, the connection id became invalid, or the native buffer write failed.
Common situations: Corrupt or mismatched runtime.node binary, runtime crash immediately after launch, OOM-killed runtime process, platform-native binary version mismatch with the SDK.
Related errors
- The in-process runtime connection is closed.
- Unsupported architecture
- An in-process FFI runtime library is already loaded from
- FFI runtime library not found at
- copilot_runtime_host_start failed
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/ee690c7b94d9cade.
Report an issue: GitHub.
Appendix: source
Thrown at nodejs/src/ffiRuntimeHost.ts:248
this.lib.hostShutdown(this.serverId);
this.serverId = 0;
throw new Error("copilot_runtime_connection_open failed.");
}
// The in-process transport has no socket/pipe handle to keep the Node event loop
// alive while the SDK is idle awaiting a server→client frame. koffi delivers the
// outbound callback on the loop but does not reference it, so hold one referenced
// timer for the lifetime of the connection.
this.keepAliveTimer = setInterval(() => {}, KEEP_ALIVE_INTERVAL_MS);
}
private writeFrame(frame: Buffer): void {
if (this.disposed || !this.connectionId) {
throw new Error("The in-process runtime connection is closed.");
}
const ok = this.lib.connectionWrite(this.connectionId, frame, frame.length);
if (!ok) {
throw new Error("Failed to write a frame to the in-process runtime connection.");
}
}
/**
* Native outbound (server→client) callback. koffi delivers it on the JS event loop
* via a threadsafe function, so the frame is decoded and written straight to
* {@link receiveStream}. The native pointer is only valid for this call, so the
* bytes are copied out before returning.
*/
private feedInbound(bytesPtr: unknown, bytesLen: number | bigint): void {
// An exception thrown across the native→JS (Node-API) boundary cannot propagate
// and would surface only as a DEP0168 "uncaught Node-API callback exception"
// warning, so catch and log it here instead of letting it escape.
try {
// A native outbound callback can still be delivered on the event loop after
// dispose() has ended receiveStream; writing then would throw
// ERR_STREAM_WRITE_AFTER_END. Drop late frames instead — the connection is
// gone and nothing is reading them.View on GitHub (pinned to cd8cf15dc3)