Hmbown/CodeWhale · error

read remaining typed input

Error message

read remaining typed input

What it means

After the reply check, the test drops the writer and calls `reader.read_to_end(&mut remaining).expect("read remaining typed input")` to drain the buffered typed suffix. The expect panics if the read fails — an I/O error on the pipe descriptor rather than a clean EOF, which is what a healthy pipe produces after the writer is dropped.

Solutions

  1. Confirm `read_terminal_reply` left the reader fd valid and positioned after the reply
  2. Drop the writer before read_to_end so EOF terminates the drain (the test already does this — verify ordering after edits)
  3. Handle `ErrorKind::Interrupted` with a retry loop if signals are common in the environment
  4. Inspect the io::Error message for the real cause (EBADF vs EIO)

Example fix

// before
reader.read_to_end(&mut remaining).expect("read remaining typed input");
// after
reader.read_to_end(&mut remaining)
    .unwrap_or_else(|e| panic!("drain failed: {e}"));
Defensive patterns

Strategy: try-catch

Try / catch

reader.read_to_end(&mut remaining)
    .unwrap_or_else(|e| panic!("pipe drain failed: {e}"));

Prevention

When it happens

Trigger: The pipe's reader descriptor hitting an I/O error during drain (underlying fd closed twice, corruption from a prior failed read in `read_terminal_reply`); platform-specific errors on read_to_end after HUP.

Common situations: A previous step in the same test panicked and left the reader in a bad state while unwinding; sandboxed environments reporting unexpected errors on pipes; reading after an external close of the fd.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/cebd2b18f76286fa. Report an issue: GitHub.

Appendix: source

Thrown at crates/palette/src/osc11_tests.rs:64

        let burst = [prefix.as_slice(), case.response, suffix.as_slice()].concat();
        assert_eq!(
            writer.write(&burst).expect("write one input burst"),
            burst.len()
        );

        // Keep the writer open: a buffered read-ahead must not be rescued by
        // EOF/readable-HUP while the real tty would have no new bytes ready.
        let (answered, reply, carried) = read_terminal_reply(
            reader.as_raw_fd(),
            case.query,
            Duration::from_secs(1),
            case.csi,
        );
        drop(writer);
        let mut remaining = Vec::new();
        reader
            .read_to_end(&mut remaining)
            .expect("read remaining typed input");

        assert!(
            answered,
            "complete reply was already on the pipe: {:?}",
            case.response
        );
        assert_eq!(reply, case.reply, "query {:?}", case.query);
        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"
        );
    }
}

View on GitHub (pinned to 433685b202)