janhq/jan · error · io::Error
Failed to read name for tensor
Error message
Failed to read name for tensor {}: {} What it means
While walking the tensor-info block in find_gguf_tensors, the u64-prefixed name string for tensor i could not be read (bad length prefix, truncated file, or desynchronized stream). The wrapper re-tags the underlying I/O or UTF-8 error with the tensor index so the corrupt record is identified.
Solutions
- Re-download the model file and verify its checksum
- Ensure the reader you pass is seekable over the complete file (not a partial stream)
- Check the file is GGUF version >= 2; v1 files misparse and desynchronize the walk
- Use llama.cpp's gguf_dump to locate exactly where the file structure breaks
Example fix
// before
let f = std::fs::File::open("partial-shard-00001-of-00002.gguf")?;
let found = find_gguf_tensors(f, &wanted)?;
// after
let f = std::fs::File::open("model.gguf")?;
let meta = std::fs::metadata("model.gguf")?;
if meta.len() < expected_min_size { anyhow::bail!("file truncated; re-download"); }
let found = find_gguf_tensors(f, &wanted)?; Defensive patterns
Strategy: validation
Validate before calling
fn file_looks_complete(path: &std::path::Path, min_bytes: u64) -> io::Result<bool> {
Ok(std::fs::metadata(path)?.len() >= min_bytes)
}
// check before opening the reader for find_gguf_tensors Prevention
- Verify file size and checksum after download before parsing
- Parse GGUF files only from complete, locally stored files (not partial streams)
- Log the tensor index from the error to locate the corruption point
When it happens
Trigger: Calling find_gguf_tensors on a file where the tensor-info block is truncated mid-name, the preceding walk desynchronized (bad version/dims), or a tensor name length prefix points past EOF.
Common situations: Partially downloaded GGUF shards (only first shard parsed), files spliced or edited by conversion scripts, v1 files or other formats misread as v2/v3, memory-corrupted model caches.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- Array length is unreasonably large
- Error reading metadata entry
- Failed to read key for metadata entry
- String length is unreasonably large
- tensor claims dimensions
AI-assisted analysis of janhq/jan@7205d770c1 (2026-09-17).
Data as JSON: /api/errors/9dbdc8195abd1d11.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/plugins/tauri-plugin-llamacpp/src/gguf/helpers.rs:60
// v1 sized strings and dimensions with u32s. llama.cpp refuses that
// version outright, and reading it as v2 would invent names.
if meta.version < 2 {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("GGUF version {} has no readable tensor block", meta.version),
));
}
if meta.tensor_count > MAX_TENSORS {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("tensor count {} is unreasonably large", meta.tensor_count),
));
}
let mut found: Vec<String> = Vec::new();
for i in 0..meta.tensor_count {
let name = read_gguf_string(&mut file).map_err(|e| {
io::Error::new(
io::ErrorKind::InvalidData,
format!("Failed to read name for tensor {}: {}", i, e),
)
})?;
let n_dims = file.read_u32::<LittleEndian>()?;
if n_dims > MAX_TENSOR_DIMS {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("tensor {} claims {} dimensions", i, n_dims),
));
}
// Read rather than seek: BufReader drops its buffer on every seek, so
// skipping this way costs a syscall per tensor on a large model.
for _ in 0..n_dims {
file.read_u64::<LittleEndian>()?;
}
file.read_u32::<LittleEndian>()?; // ggml type
file.read_u64::<LittleEndian>()?; // offset into the data sectionView on GitHub (pinned to 7205d770c1)