sxyazi/yazi · info · PeekError::Unexpected

Binary file

Error message

Binary file

What it means

The highlighter peeks files line by line and scans the inspected prefix with is_binary; as soon as a binary signature (NUL and similar bytes) is found it stops with Err(anyhow!("Binary file")) surfaced as a PeekError. This is intentional: syntax highlighting is refused for non-text content rather than rendering garbage.

Source

Thrown at yazi-core/src/highlighter.rs:73

			syntaxes,
			syntax: None,
		})
	}

	pub fn abort() { INCR.next(); }

	fn highlight(mut self) -> Result<Text<'static>, PeekError> {
		self.load_syntax()?;
		let mut plain = self.syntax.is_none();
		let mut h = self.syntax.map(|syntax| HighlightLines::new(syntax, &self.theme));

		let mut i = 0;
		let mut buf = vec![];
		let mut lines = Vec::with_capacity(self.size.height as usize);
		let mut inspected = 0u16;
		while self.reader.read_until(b'\n', &mut buf).is_ok_and(|n| n > 0) {
			if Self::is_binary(&buf, &mut inspected) {
				Err(anyhow!("Binary file"))?;
			}

			let remaining = Self::normalize_control_chars(&mut buf);
			if remaining || buf.len() > 5000 {
				plain = true;
			}

			self.ensure_not_cancelled()?;
			if plain && !self.process_plain(&buf, &mut i, &mut lines)? {
				break;
			} else if !plain && !self.process_hyper(&buf, &mut i, &mut lines, h.as_mut())? {
				break;
			}
			buf.clear();
		}

		if self.skip > 0 && i < self.skip + self.size.height as usize {
			return Err(PeekError::Exceeded(i.saturating_sub(self.size.height as _)));

View on GitHub (pinned to 94abcfa92f)

Solutions

  1. Treat it as expected signal: catch this PeekError and render the fallback (placeholder) preview
  2. Add a filetype rule in yazi.toml routing that extension/mime to an appropriate previewer
  3. For UTF-16 files, register an external previewer that transcodes, or convert the file

Example fix

// before
let text = highlighter.highlight().await?;

// after
let text = match highlighter.highlight().await {
    Ok(t) => t,
    Err(e) if e.to_string() == "Binary file" => return render_fallback(),
    Err(e) => return Err(e),
};
Defensive patterns

Strategy: fallback

Validate before calling

// Cheap pre-check: sniff for NUL bytes before highlighting.
use std::io::Read;
let mut probe = [0; 4096];
let n = std::fs::File::open(&path)?.read(&mut probe)?;
if probe[..n].contains(&0) {
    return render_fallback(); // skip the highlighter entirely
}

Type guard

fn looks_binary(prefix: &[u8]) -> bool { prefix.contains(&0) }

Try / catch

match highlighter.highlight().await {
    Ok(t) => t,
    Err(e) if e.to_string() == "Binary file" => render_fallback(),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Previewing a file that reaches the text-preview path but contains binary bytes in its first lines: unrecognized binaries (no filetype rule matched), files with embedded NULs, or UTF-16 text whose NUL bytes trip the detector.

Common situations: Extensionless/misdetectced binaries falling through to text preview; UTF-16 files; plugins not registering a previewer for a custom binary mime type.


AI-assisted analysis of sxyazi/yazi@94abcfa92f (2026-08-16). Data as JSON: /api/errors/eff6dc1621ce6d71. Report an issue: GitHub.