janhq/jan · error · KVCacheError
HeadCountInvalid
HeadCountInvalid
Error message
Invalid metadata: head_count not found or invalid
What it means
KVCacheError::HeadCountInvalid is raised when the GGUF metadata lacks a valid `head_count` (attention head count) key. The KV-cache construction needs this to dimension per-head tensors, so it rejects the model if the key is missing or unreadable. Like the other Invalid-metadata variants, it points at a bad or unsupported GGUF file.
Solutions
- Re-download the GGUF file from the original source and verify integrity.
- Dump metadata (e.g. gguf-dump) and confirm `head_count` is present with a sane positive value.
- Re-convert the model with current llama.cpp conversion scripts to regenerate complete metadata.
- Update the plugin if the model uses a newer architecture naming scheme it doesn't recognize.
Example fix
// before
let cache = kv_cache::from_gguf(&model_path).unwrap();
// after
match kv_cache::from_gguf(&model_path) {
Ok(c) => c,
Err(KVCacheError::HeadCountInvalid) => {
anyhow::bail!("model file lacks head_count metadata; re-download or re-convert the GGUF")
}
Ok => unreachable!(),
} Defensive patterns
Strategy: validation
Validate before calling
// Rust: check head_count key before loading
fn has_head_count(md: &GgufMetadata, arch: &str) -> bool {
md.get_u64(&format!("{arch}.head_count")).map(|v| v > 0).unwrap_or(false)
} Type guard
fn valid_u64(v: Option<&u64>) -> bool {
matches!(v, Some(n) if *n > 0)
} Try / catch
match kv_cache::from_gguf(&path) {
Err(KVCacheError::HeadCountInvalid) => anyhow::bail!("GGUF missing head_count; re-download model"),
other => other?,
} Prevention
- Validate model metadata keys once at app startup for bundled models.
- Re-convert legacy GGUF files with updated llama.cpp scripts.
- Log which metadata keys are missing to speed up diagnosis.
When it happens
Trigger: Loading a GGUF model whose metadata map is missing `{arch}.head_count`, or whose value cannot be parsed into the expected integer type during KV-cache setup.
Common situations: Corrupt or incomplete model downloads; models converted by third-party tools that omit head_count; architectures whose key prefix differs from what the reader expects.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- BlockCountInvalid
- ContextLengthInvalid
- EmbeddingLengthInvalid
- Invalid metadata: architecture not found
- Invalid metadata: block_count not found or invalid
AI-assisted analysis of janhq/jan@7205d770c1 (2026-09-17).
Data as JSON: /api/errors/8c172a0f8219e8ce.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/plugins/tauri-plugin-llamacpp/src/gguf/types.rs:67
#[derive(Serialize)]
pub struct GgufMetadata {
pub version: u32,
pub tensor_count: u64,
pub metadata: HashMap<String, String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct KVCacheEstimate {
pub size: u64,
pub per_token_size: u64,
}
#[derive(Debug, thiserror::Error)]
pub enum KVCacheError {
#[error("Invalid metadata: architecture not found")]
ArchitectureNotFound,
#[error("Invalid metadata: block_count not found or invalid")]
BlockCountInvalid,
#[error("Invalid metadata: head_count not found or invalid")]
HeadCountInvalid,
#[error("Invalid metadata: embedding_length not found or invalid")]
EmbeddingLengthInvalid,
#[error("Invalid metadata: context_length not found or invalid")]
ContextLengthInvalid,
}
impl serde::Serialize for KVCacheError {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
#[derive(Debug, Clone, Copy, PartialEq, serde::Serialize)]View on GitHub (pinned to 7205d770c1)