janhq/jan · error · io::Error
tensor claims dimensions
Error message
tensor {} claims {} dimensions What it means
find_gguf_tensors rejects a tensor-info record whose n_dims exceeds MAX_TENSOR_DIMS (4, the GGML_MAX_DIMS value). GGUF tensors can never have more than 4 dimensions, so a larger rank means the byte walk has desynchronized or the file is corrupt, not that an exotic tensor shape exists.
Solutions
- Re-download or regenerate the model file and verify its checksum
- Confirm the file is GGUF version 2 or 3 (version < 2 is otherwise refused); use a hex dump on the first bytes
- Locate the corrupt tensor with llama.cpp's gguf_dump before re-converting
- If you control the file pipeline, check the exporter's dimension-count serialization
Example fix
// before
let bytes = std::fs::read("legacy-v1-model.gguf")?;
let found = find_gguf_tensors(Cursor::new(bytes), &wanted)?;
// after
let bytes = std::fs::read("model.gguf")?;
// ensure GGUF v2/v3: version stored as u32 LE at offset 4
let version = u32::from_le_bytes(bytes[4..8].try_into().unwrap());
assert!(version >= 2, "convert v1 file first");
let found = find_gguf_tensors(Cursor::new(bytes), &wanted)?; Defensive patterns
Strategy: validation
Validate before calling
fn is_supported_gguf_version(bytes: &[u8]) -> bool {
bytes.len() >= 8
&& &bytes[0..4] == b"GGUF"
&& u32::from_le_bytes(bytes[4..8].try_into().unwrap()) >= 2
}
// v1 files desynchronize the walk; refuse them up front Prevention
- Convert legacy GGUF v1 files to v2/v3 before loading
- Never edit tensor-info blocks by hand
- Validate models with gguf_dump once after download
When it happens
Trigger: Calling find_gguf_tensors on a file where tensor i's u32 dimension count is > 4 - caused by corruption, a v1 file being read as v2 (u32 vs u64 layout shift), or misaligned parsing after a bad earlier record.
Common situations: Reading legacy GGUF v1 files, hand-edited or corrupted model files, feeding non-GGUF tensors, conversion bugs writing malformed tensor-info entries.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- tensor count is unreasonably large
- Array length is unreasonably large
- Error reading metadata entry
- Failed to read key for metadata entry
- Failed to read name for tensor
AI-assisted analysis of janhq/jan@7205d770c1 (2026-09-17).
Data as JSON: /api/errors/a082bf9b9e368bfa.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/plugins/tauri-plugin-llamacpp/src/gguf/helpers.rs:67
}
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 section
if wanted.contains(&name) && !found.contains(&name) {
found.push(name);
if found.len() == wanted.len() {
break;
}
}View on GitHub (pinned to 7205d770c1)