astral-sh/ruff · error · io::Error
Invalid UTF-8 in JUnit report
Error message
Invalid UTF-8 in JUnit report
What it means
This io::Error (kind InvalidData) is produced by ruff's JUnit report `FmtAdapter`, a `std::io::Write` adapter that forwards bytes to `fmt::Write`. Because `fmt::Write` only accepts strings, the adapter validates each incoming buffer as UTF-8 and fails with this message if it is not.
Source
Thrown at crates/ruff_db/src/diagnostic/render/junit.rs:177
.entry(filename)
.or_insert_with(Vec::new)
.push(DiagnosticWithLocation {
diagnostic,
start_location,
});
}
grouped_diagnostics
}
struct FmtAdapter<'a> {
fmt: &'a mut dyn std::fmt::Write,
}
impl std::io::Write for FmtAdapter<'_> {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.fmt
.write_str(std::str::from_utf8(buf).map_err(|_| {
std::io::Error::new(
std::io::ErrorKind::InvalidData,
"Invalid UTF-8 in JUnit report",
)
})?)
.map_err(std::io::Error::other)?;
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
fn write_fmt(&mut self, args: std::fmt::Arguments<'_>) -> std::io::Result<()> {
self.fmt.write_fmt(args).map_err(std::io::Error::other)
}
}
View on GitHub (pinned to 26f38c119c)
Solutions
- Ensure all content written to the JUnit report is valid UTF-8 (decode with lossy conversion at the source)
- Check where non-UTF-8 bytes enter the report (often a source file read); normalize with `String::from_utf8_lossy`
- Route byte output through an explicit encoding step before the JUnit writer
Example fix
// before adapter.write_all(raw_bytes)?; // may contain invalid UTF-8 // after adapter.write_all(String::from_utf8_lossy(raw_bytes).as_bytes())?;
Defensive patterns
Strategy: try-catch
Validate before calling
if let Err(e) = std::str::from_utf8(buf) {
eprintln!("non-UTF-8 content for JUnit report: {e}");
}
let safe = String::from_utf8_lossy(buf); Type guard
fn is_valid_utf8(buf: &[u8]) -> bool {
std::str::from_utf8(buf).is_ok()
} Try / catch
match write_result {
Err(e) if e.kind() == std::io::ErrorKind::InvalidData => {
eprintln!("JUnit report content was not valid UTF-8");
}
Err(e) => return Err(e),
Ok(n) => n,
} Prevention
- Decode all external input with from_utf8_lossy before formatting into reports
- Keep report writers string-level end to end
- Add a test that writes non-ASCII and binary content through the report pipeline
When it happens
Trigger: Writing bytes that are not valid UTF-8 into a JUnit-format report writer — e.g. `write!` with content derived from non-UTF-8 data, or downstream code that pushes raw byte slices into the adapter.
Common situations: Diagnostics containing text decoded from files with non-UTF-8 encodings, lossy conversions upstream, or mixing a byte-level writer API with the string-level JUnit formatter.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- InvalidUtf8
- stream did not contain valid UTF-8
- InvalidInput
- failed to resolve uv executable: {error}
- Expected a valid noqa code corresponding to a rule
AI-assisted analysis of astral-sh/ruff@26f38c119c (2026-09-05).
Data as JSON: /api/errors/504040c6cceecc08.
Report an issue: GitHub.