janhq/jan · error · io::Error

Failed to read key for metadata entry {}: {}

Error message

Failed to read key for metadata entry {}: {}

What it means

Returned by `read_metadata_entry` when `read_gguf_string` fails on the entry's key. A metadata key is encoded as a u64 little-endian length followed by that many UTF-8 bytes; this error fires if the length read fails (EOF), the length is unreasonable (see error 83), the byte read fails, or the bytes are not valid UTF-8. The wrapper adds the entry index so the caller knows which key broke.

Source

Thrown at src-tauri/plugins/tauri-plugin-llamacpp/src/gguf/helpers.rs:50

                    format!("Error reading metadata entry {}: {}", i, e),
                ));
            }
        }
    }

    Ok(GgufMetadata {
        version,
        tensor_count,
        metadata: metadata_map,
    })
}

fn read_metadata_entry<R: Read + Seek + ReadBytesExt>(
    reader: &mut R,
    index: u64,
) -> io::Result<(String, String)> {
    let key = read_gguf_string(reader).map_err(|e| {
        io::Error::new(
            io::ErrorKind::InvalidData,
            format!("Failed to read key for metadata entry {}: {}", index, e),
        )
    })?;

    let value_type_u32 = reader.read_u32::<LittleEndian>()?;
    let value_type = GgufValueType::try_from(value_type_u32)?;
    let value = read_gguf_value(reader, value_type)?;

    Ok((key, value))
}

fn read_gguf_string<R: Read + ReadBytesExt>(reader: &mut R) -> io::Result<String> {
    let len = reader.read_u64::<LittleEndian>()?;
    if len > (1024 * 1024) {
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            format!("String length {} is unreasonably large", len),

View on GitHub (pinned to fad3f12a14)

Solutions

  1. Inspect the inner error: "unreasonably large" points to misalignment/corruption; a Utf8Error points to non-text bytes; EOF points to truncation.
  2. If misalignment is suspected (e.g. after a skipped array), audit `skip_array_data` against the GGUF spec for the offending element type.
  3. Re-verify the file checksum and re-download if corrupted.
  4. Try a different GGUF of the same architecture to determine if the bug is file-specific or parser-specific.

Example fix

// before
let key = read_gguf_string(reader).map_err(|e| io::Error::new(InvalidData,
    format!("Failed to read key for metadata entry {}: {}", index, e)))?;

// after - log reader position before the failing read
let pos = reader.stream_position().unwrap_or(0);
let key = read_gguf_string(reader).map_err(|e| io::Error::new(InvalidData,
    format!("key read failed at entry {} (byte {}): {}", index, pos, e)))?;
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

null

Try / catch

match read_gguf_metadata(reader) {
    Ok(m) => Ok(m),
    Err(e) if e.to_string().contains("Failed to read key") => {
        Err(InvalidModel(format!("metadata key read failed: {e}")))
    }
    Err(e) => Err(e.into()),
}

Prevention

When it happens

Trigger: A metadata kv entry whose key length field is unparseable (file truncated at the length field), whose declared length exceeds 1 MiB, or whose bytes are not UTF-8 (e.g. a binary blob mistaken for a key). Also fires if the previous value read consumed the wrong number of bytes, leaving the stream misaligned at the next key.

Common situations: Misaligned stream after an array value was skipped with the wrong stride; truncated download; a quantized GGUF produced by a tool whose key encoding differs. The error message itself includes the inner cause (e.g. "unreasonably large" or a Utf8Error) which pinpoints the sub-failure.

Related errors


AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12). Data as JSON: /api/errors/0dcb3cee71b8ed32. Report an issue: GitHub.