rtk-ai/rtk · error · anyhow::Error
Failed to parse binlog at {}: empty file
Error message
Failed to parse binlog at {}: empty file What it means
This error is thrown when a .binlog file exists but has zero bytes. parse_events_from_binlog reads the whole file first and bails out early because an empty buffer cannot contain the binlog magic header, let alone any build events.
Source
Thrown at src/cmds/dotnet/binlog.rs:303
project_files: HashSet<String>,
errors: Vec<BinlogIssue>,
warnings: Vec<BinlogIssue>,
build_succeeded: Option<bool>,
build_started_ticks: Option<i64>,
build_finished_ticks: Option<i64>,
}
#[derive(Default)]
struct ParsedEventFields {
message: Option<String>,
timestamp_ticks: Option<i64>,
}
fn parse_events_from_binlog(path: &Path) -> Result<ParsedBinlog> {
let bytes = std::fs::read(path)
.with_context(|| format!("Failed to read binlog at {}", path.display()))?;
if bytes.is_empty() {
anyhow::bail!("Failed to parse binlog at {}: empty file", path.display());
}
let mut decoder = GzDecoder::new(bytes.as_slice());
let mut payload = Vec::new();
decoder.read_to_end(&mut payload).with_context(|| {
format!(
"Failed to parse binlog at {}: gzip decode failed",
path.display()
)
})?;
let mut reader = BinReader::new(&payload);
let file_format_version = reader
.read_i32_le()
.context("binlog header missing file format version")?;
let _minimum_reader_version = reader
.read_i32_le()
.context("binlog header missing minimum reader version")?;View on GitHub (pinned to 36788f6bd4)
Solutions
- Delete and regenerate the binlog by re-running the build/test with /bl (or rtk's wrapping command)
- Check disk space and that no external process truncates the file
- Verify the file with `ls -l` / `wc -c` to confirm it is genuinely 0 bytes and not a path mistake
- Run with rtk proxy or raw dotnet to confirm the underlying build itself succeeds
Example fix
// before: parsing a possibly-empty file blindly
let binlog = parse_events_from_binlog(&path)?;
// after: guard before calling
if path.metadata()?.len() == 0 { eprintln!("binlog is empty, rerun build with /bl"); } else { let binlog = parse_events_from_binlog(&path)?; } Defensive patterns
Strategy: validation
Validate before calling
use std::path::Path;
fn binlog_is_parseable(path: &Path) -> std::io::Result<bool> {
Ok(path.metadata()?.len() > 0)
} Try / catch
match parse_events_from_binlog(&path) {
Ok(binlog) => use_events(&binlog),
Err(e) if e.to_string().contains("empty file") => {
eprintln!("binlog {} is empty; rerun the build with /bl", path.display());
}
Err(e) => return Err(e),
} Prevention
- Check file size > 0 before parsing
- Ensure builds with /bl complete and are never killed mid-write
- Monitor disk space in CI
- Treat 0-byte artifacts as build failures in the pipeline
When it happens
Trigger: Calling rtk dotnet build/test/restore (which invoke parse_build/parse_test/parse_restore) with a .binlog path that points to a 0-byte file — e.g. the logger was attached but MSBuild crashed before writing anything, or the file was truncated by disk-full/cleanup.
Common situations: MSBuild launched with /bl but killed before flush; antivirus or a cleaner truncated the file; a wrapper script created the file but the build failed instantly; passing the wrong path variable that happens to be an empty touched file.
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
- Failed to parse binlog at {}: unsupported binlog format {}
- negative record length: {}
- negative event length: {}
- legacy dictionary format is unsupported
- unexpected end of stream
AI-assisted analysis of rtk-ai/rtk@36788f6bd4 (2026-09-03).
Data as JSON: /api/errors/a75d843fa110b9b8.
Report an issue: GitHub.