atuinsh/atuin · info
writing to a String cannot fail
Error message
writing to a String cannot fail
What it means
`on_scroll` writes vt100 row contents into a `String` buffer via `write_formatted_basic` and unwraps the `Result` with `.expect("writing to a String cannot fail")`. The error type from rmp/vt100-style writers cannot occur when the target is a `String` (no capacity or IO errors), so this is an infallibility assertion, not a real runtime failure.
Solutions
- Pin/upgrade the `vt100` crate and confirm `write_formatted_basic` still returns an infallible-for-String error type
- If it can now fail, propagate the error instead of expecting
Defensive patterns
Strategy: try-catch
Try / catch
// infallible in practice; if the vt100 API becomes fallible:
if let Err(e) = contents.write_formatted_basic(&mut self.buffer, &mut self.state) {
log::warn!("failed to format scroll contents: {e}");
return;
} Prevention
- Pin the vt100 crate version and review its changelog on upgrade
- Add a comment/doc test asserting String writes remain infallible
When it happens
Trigger: Only via a library bug: the underlying `write_formatted_basic` implementation returning `Err` despite writing to a `String` (e.g. a breaking change in the vt100 crate's API contract).
Common situations: Effectively never; appears in terminal scrollback rendering inside the TUI when new screen contents are captured.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- writing to a Vec is infallible
- Atuin running with no parent!
- clone pty reader
- Could not build config
- Could not build default
AI-assisted analysis of atuinsh/atuin@900007c480 (2026-09-19).
Data as JSON: /api/errors/ecadee7d9dfe5847.
Report an issue: GitHub.
Appendix: source
Thrown at crates/atuin-common/src/ansi.rs:59
if !std::mem::take(&mut first) {
// Trim the end of the line that was pushed in the previous iteration, and add
// the newline that we didn't push.
plain_contents.trim_end_matches_in_place([' ', '\t']);
plain_contents.push('\n');
}
plain_contents.push_str(plain_line);
}
}
}
impl vt100::Callbacks for Capture {
fn on_scroll(&mut self, contents: vt100::capture::RowContents<'_>, alternate_screen: bool) {
if alternate_screen {
return;
}
contents
.write_formatted_basic(&mut self.buffer, &mut self.state)
.expect("writing to a String cannot fail");
push_formatted(&mut self.plain_contents, &self.buffer);
self.buffer.clear();
}
}
if input.is_empty() {
return String::new();
}
let mut parser = vt100::Parser::new_with_callbacks(rows, cols, 0, Capture::default());
onlcr(input).for_each(|chunk| parser.process(chunk));
let (screen, capture) = parser.screen_and_callbacks_mut();
screen
.write_contents_formatted_basic(
&mut capture.buffer,
vt100::capture::BasicFormattedCaptureRange::Full(&mut capture.state),
)View on GitHub (pinned to 900007c480)