vectordotdev/vector · error · io::Error
UnexpectedEof
UnexpectedEof
Error message
EOF reached
What it means
The file source's fingerprinter reads the first N lines (up to `fingerprint.lines`, after `ignored_header_bytes`) of a file to compute its identity checksum, using `fingerprinter_read_until` to fill a fixed buffer. A read returning `Ok(0)` before the buffer is full means end-of-file was hit prematurely, and it is surfaced as `UnexpectedEof` ("EOF reached"). This typically means the file is too short for the configured fingerprint window (including gzip inputs whose decompressed head is smaller than needed).
Source
Thrown at lib/file-source-common/src/fingerprinter.rs:256
};
// For scenarios other than UnexpectedEOF, remove the path from the small files map.
known_small_files.remove(&path.to_path_buf());
})
.ok()
.flatten()
}
}
async fn fingerprinter_read_until(
mut r: impl AsyncRead + Unpin + Send,
delim: u8,
mut count: usize,
mut buf: &mut [u8],
) -> Result<usize> {
let mut total_read = 0;
'main: while !buf.is_empty() {
let read = match r.read(buf).await {
Ok(0) => return Err(std::io::Error::new(ErrorKind::UnexpectedEof, "EOF reached")),
Ok(n) => n,
Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) => return Err(e),
};
for (pos, &c) in buf[..read].iter().enumerate() {
if c == delim {
if count <= 1 {
total_read += pos + 1;
break 'main;
} else {
count -= 1;
}
}
}
total_read += read;
buf = &mut buf[read..];
}View on GitHub (pinned to 3708c39b12)
Solutions
- Keep `fingerprint.lines` at 1 (default) unless every matched file is guaranteed longer.
- Tighten the glob (`exclude_files`, or match `*.log` only) so transient empty/partial files being written are not fingerprinted.
- If identical first lines across files force a bigger window, ensure `fingerprint.lines` stays below the smallest real file's line count, or switch `fingerprint.strategy` to `devino` (inode-based, no content read).
- Verify `ignored_header_bytes` is smaller than the files being matched.
Example fix
# before
sources:
logs:
type: file
include: ["/var/log/app/*"]
fingerprint:
lines: 5
# short files (<5 lines) hit UnexpectedEof
# after
sources:
logs:
type: file
include: ["/var/log/app/*.log"]
fingerprint:
lines: 1 Defensive patterns
Strategy: validation
Validate before calling
# Config-side: keep fingerprint window within the smallest file fingerprint: strategy: checksum lines: 1 ignored_header_bytes: 0 # Deploy-time: fail if any matched file is smaller than the window find /var/log/app -name '*.log' -size -1k -print -quit | grep -q . && \ echo 'WARN: files smaller than fingerprint window matched by glob'
Prevention
- Use tight globs and exclude_files for transient/empty files.
- Keep fingerprint.lines = 1 unless every matched file is provably longer.
- If unavoidable, switch to fingerprint.strategy = "devino" (no content read, at the cost of identity surviving inode reuse poorly on some filesystems).
When it happens
Trigger: A globbed file smaller than the fingerprint buffer/line requirement — e.g. `fingerprint.lines = 1` on an empty file being written, or higher `lines` on a file with fewer lines; files with more `ignored_header_bytes` than actual content; a gzip member header that decompresses to fewer bytes than requested.
Common situations: Log rotation leaving zero-byte or one-line stub files matched by the glob; setting `fingerprint.lines` > 1 (as some guides suggest to survive identical first lines) on directories with short files; ignoring header bytes of files without those headers.
Related errors
- failed to read glob pattern
- not a valid path
- path and query should never fail to parse
- Serializer does not support JSON
- Paths must always start with a leading forward slash (`/`).
AI-assisted analysis of vectordotdev/vector@3708c39b12 (2026-08-20).
Data as JSON: /api/errors/f720ec0d27706a5c.
Report an issue: GitHub.