sxyazi/yazi · error

path too long

Error message

path too long

What it means

On Windows, final_name first queries FileNormalizedNameInfo with a 512-u16 stack buffer; if the API reports it needs more, it retries with a heap buffer of that size. A second failure means the name still doesn't fit, so it returns 'path too long'.

Solutions

  1. Shorten the path or move the file closer to the root
  2. Use the \\?\ extended-length prefix for very long paths
  3. Retry — a concurrent rename may have invalidated the length probe
Defensive patterns

Strategy: try-catch

Validate before calling

// give the API an oversized buffer up front to avoid the two-step path
let mut buf = vec![0u16; 1024]; // 2048 bytes covers virtually all normalized names

Try / catch

match Casefold::final_name(path) {
    Ok(n) => n,
    Err(e) if e.kind() == std::io::ErrorKind::InvalidData => shorten_and_retry(path),
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: A file whose normalized name exceeds even the API-reported buffer length — path component lengths near the 32k limit, or the handle query raced with a rename that grew the name.

Common situations: Extremely deep directory trees with long Unicode names; network paths (UNC) with very long components; files being renamed concurrently.

Understand the failure class

Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.

Related errors


AI-assisted analysis of sxyazi/yazi@a541adde4e (2026-09-18). Data as JSON: /api/errors/6d225b859f278a11. Report an issue: GitHub.

Appendix: source

Thrown at yazi-fs/src/casefold/windows.rs:25

use super::Casefold;

impl Casefold {
	pub(super) fn final_name(path: &Path) -> io::Result<OsString> {
		if let Ok(name) = Self::by_find(path) {
			return Ok(name);
		}

		let file = OpenOptions::new()
			.access_mode(0)
			.custom_flags(FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT)
			.open(path)?;

		match Self::by_handle(&file, &mut [0u16; 512])? {
			Either::Left(name) => Ok(name),
			Either::Right(len) => match Self::by_handle(&file, &mut vec![0u16; len as usize])? {
				Either::Left(name) => Ok(name),
				Either::Right(_) => Err(io::Error::new(ErrorKind::InvalidData, "path too long")),
			},
		}
	}

	fn by_find(path: &Path) -> io::Result<OsString> {
		Self::check_name(path)?;
		let wide = path.to_wide();

		let mut data = unsafe { mem::zeroed::<WIN32_FIND_DATAW>() };
		let handle = unsafe {
			FindFirstFileExW(
				wide.as_ptr(),
				FindExInfoBasic,
				(&raw mut data).cast(),
				FindExSearchNameMatch,
				ptr::null(),
				0,
			)

View on GitHub (pinned to a541adde4e)