{"record":{"id":"0232f76b439f942e","repo":"janhq/jan","slug":"not-a-gguf-file","errorCode":null,"errorMessage":"Not a GGUF file","messagePattern":"Not a GGUF file","errorType":"validation","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"src-tauri/plugins/tauri-plugin-llamacpp/src/gguf/helpers.rs","lineNumber":13,"sourceCode":"use byteorder::{LittleEndian, ReadBytesExt};\nuse std::convert::TryFrom;\nuse std::io::{self, BufReader, Read, Seek};\n\nuse super::types::{GgufMetadata, GgufValueType};\n\npub fn read_gguf_metadata<R: Read + Seek>(reader: R) -> io::Result<GgufMetadata> {\n    let mut file = BufReader::new(reader);\n\n    let mut magic = [0u8; 4];\n    file.read_exact(&mut magic)?;\n    if &magic != b\"GGUF\" {\n        return Err(io::Error::new(\n            io::ErrorKind::InvalidData,\n            \"Not a GGUF file\",\n        ));\n    }\n\n    let version = file.read_u32::<LittleEndian>()?;\n    let tensor_count = file.read_u64::<LittleEndian>()?;\n    let metadata_count = file.read_u64::<LittleEndian>()?;\n\n    let mut metadata_map = std::collections::HashMap::new();\n    for i in 0..metadata_count {\n        match read_metadata_entry(&mut file, i) {\n            Ok((key, value)) => {\n                metadata_map.insert(key, value);\n            }\n            Err(e) => {\n                return Err(io::Error::new(\n                    io::ErrorKind::InvalidData,","sourceCodeStart":1,"sourceCodeEnd":31,"githubUrl":"https://github.com/janhq/jan/blob/fad3f12a147d138388a66f0d92a02b2675f65294/src-tauri/plugins/tauri-plugin-llamacpp/src/gguf/helpers.rs#L1-L31","documentation":"Thrown by `read_gguf_metadata` after reading the first 4 bytes of the file and comparing them against the ASCII bytes `b\"GGUF\"`. The GGUF format always starts with this 4-byte magic header (offset 0). If the comparison fails, the file is not a valid GGUF container, so the parser aborts before reading version/tensor/metadata counts. It is returned as `io::Error` with kind `InvalidData`.","triggerScenarios":"Calling `read_gguf_metadata(reader)` with any non-GGUF input: a GGML (legacy) file, a safetensors/ckpt/bin file, a partially-downloaded GGUF whose header is truncated to fewer than 4 bytes, or an empty file (read_exact then returns UnexpectedEof before the comparison is reached). Passing a file opened on a path that resolved to a directory or a text file produces the same outcome.","commonSituations":"Downloading a model from a URL that returned an HTML error page, mistaking a GGML v1 file for GGUF, pointing the loader at a `.bin` LLaMA checkpoint, or a truncated download where the magic check coincidentally still fails because the bytes are HTML/JSON. Also seen when the file handle is a different file than expected (path race, wrong symlink).","solutions":["Verify the file is actually GGUF: run `head -c 4 file.gguf | xxd` and confirm it prints `47 47 55 46` (`GGUF`).","Re-download the model from a trusted source if the magic bytes do not match; a corrupted or HTML-error-page download is the usual cause.","Confirm the path handed to `read_gguf_metadata` is the model file and not a directory, symlink target, or unrelated artifact.","If you must support legacy GGML, parse it with a separate GGML reader rather than the GGUF parser."],"exampleFix":"// before\nlet meta = read_gguf_metadata(File::open(path)?)?;\n\n// after\nlet mut f = File::open(path)?;\nlet mut magic = [0u8; 4];\nf.read_exact(&mut magic)?;\nif &magic != b\"GGUF\" {\n    return Err(io::Error::new(\n        io::ErrorKind::InvalidData,\n        format!(\"{} is not a GGUF file (magic={:?})\", path.display(), magic),\n    ));\n}\nf.seek(SeekFrom::Start(0))?;\nlet meta = read_gguf_metadata(f)?;","handlingStrategy":"validation","validationCode":"fn is_gguf(path: &Path) -> bool {\n    let mut f = match std::fs::File::open(path) {\n        Ok(f) => f,\n        Err(_) => return false,\n    };\n    let mut magic = [0u8; 4];\n    f.read_exact(&mut magic).is_ok() && &magic == b\"GGUF\"\n}\n\n// before calling read_gguf_metadata:\nif !is_gguf(&path) {\n    return Err(format!(\"{} is not a GGUF file\", path.display()));\n}","typeGuard":"null","tryCatchPattern":"match read_gguf_metadata(File::open(&path)?) {\n    Ok(meta) => Ok(meta),\n    Err(e) if e.kind() == io::ErrorKind::InvalidData && e.to_string().contains(\"Not a GGUF\") => {\n        Err(UserError::InvalidModelFile(path.display().to_string()))\n    }\n    Err(e) => Err(e.into()),\n}","preventionTips":["Validate the magic bytes before handing the file to the full parser.","Compute and compare the file's checksum against the published value before parsing.","Restrict the file picker to .gguf extensions in the UI."],"tags":["gguf","file-format","validation","llamacpp","rust"],"backgroundTag":null,"analyzedSha":"fad3f12a147d138388a66f0d92a02b2675f65294","analyzedAt":"2026-08-12T20:33:47.516Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}