Hmbown/CodeWhale · error
write incomplete reply
Error message
write incomplete reply
What it means
This is a `std::io::Write::write` Err surfaced through `expect('write incomplete reply')`, panicking the test. The library throws it when writing the synthesized terminal escape burst (`/plu` + a truncated OSC 11 reply) to the write end of the test pipe fails. Because the write end is a pipe, failure usually means the read end was already closed (EPIPE) or the descriptor is invalid — the fixture plumbing broke, not the code under test.
Solutions
- Ensure the pipe's read half stays alive until after all writes; only `drop(writer)` after writing (as this test does).
- Inspect the io::Error kind: BrokenPipe means the reader side was closed first — fix the fixture ordering.
- Handle short writes if swapping in a different writer: loop or use write_all so a partial write does not corrupt the burst.
Example fix
// before
writer.write(&burst).expect("write incomplete reply");
// after
writer.write_all(&burst).expect("pipe write half closed before burst was written"); Defensive patterns
Strategy: try-catch
Validate before calling
// verify write half is still open before writing the burst assert!(matches!(writer.write(&[]), Ok(_)), "pipe write end is closed (EPIPE) before writing burst");
Try / catch
match writer.write(&burst) {
Ok(n) if n == burst.len() => {},
Ok(n) => panic!("short write: {n}/{} bytes", burst.len()),
Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe =>
panic!("pipe reader was dropped before the burst was written: {e}"),
Err(e) => panic!("write incomplete reply: {e}"),
} Prevention
- Use write_all instead of a single write to handle partial writes.
- Keep the pipe's read half alive until all writes complete; drop the write half last.
- On write failures, assert the exact byte count rather than trusting write's return value.
When it happens
Trigger: `writer.write(&burst)` on a `std::io::pipe()` write half after the read half was dropped or closed; writing to an invalid raw fd; or a partial write loop aborted. Any Err from that call panics with this message.
Common situations: Refactoring the test so `drop(reader)` happens before the write; closing the read end in a helper; running under a sandbox where the pipe fd was closed by the environment.
Related errors
- create isolated input pipe
- Failed to write to
- read remaining typed input
- rotate fixture
- terminal input pump disconnected
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/e23b65654bd7b021.
Report an issue: GitHub.
Appendix: source
Thrown at crates/palette/src/osc11_tests.rs:90
assert_eq!(
carried, prefix,
"type-ahead before the reply must be replayable"
);
assert_eq!(
remaining, suffix,
"the input pump must still receive the exact suffix"
);
}
}
#[test]
fn terminal_reply_reader_retains_incomplete_control_reply_separately_from_typeahead() {
let (reader, mut writer) = std::io::pipe().expect("create isolated input pipe");
let prefix = b"/plu";
let incomplete = b"\x1b]11;rgb:1e/1e\r\r";
let burst = [prefix.as_slice(), incomplete.as_slice()].concat();
assert_eq!(
writer.write(&burst).expect("write incomplete reply"),
burst.len()
);
drop(writer);
let (answered, reply, carried) = read_terminal_reply(
reader.as_raw_fd(),
b"\x1b]11;?\x07",
Duration::from_secs(1),
false,
);
assert!(
!answered,
"an unterminated control reply is not a valid answer"
);
assert_eq!(
reply, incomplete,
"the caller must account for every unreplayable byte"View on GitHub (pinned to 433685b202)