huggingface/candle · error

expected numeric value for token type/id, got {v:?}

Error message

expected numeric value for token type/id, got {v:?}

What it means

Thrown by gguf_value_to_u32 when a GGUF metadata field expected to be a numeric token type/id (e.g. tokenizer.ggml.token_type or added-token ids) holds a non-numeric value such as a string, bool, array or map. The helper only accepts U8/U16/U32/I16/I32/U64/I64 GGUF value variants.

Source

Thrown at candle-core/src/quantized/tokenizer.rs:41

fn metadata_value<'a>(ct: &'a gguf_file::Content, key: &str) -> Result<&'a gguf_file::Value> {
    ct.metadata
        .get(key)
        .with_context(|| format!("missing GGUF metadata key `{key}`"))
}

fn gguf_value_to_u32(v: &gguf_file::Value) -> Result<u32> {
    use gguf_file::Value::*;
    match v {
        U8(v) => Ok(*v as u32),
        I8(v) => Ok(*v as u32),
        U16(v) => Ok(*v as u32),
        I16(v) => Ok(*v as u32),
        U32(v) => Ok(*v),
        I32(v) => Ok(*v as u32),
        U64(v) => Ok(*v as u32),
        I64(v) => Ok(*v as u32),
        _ => crate::bail!("expected numeric value for token type/id, got {v:?}"),
    }
}

fn value_to_string_array(v: &gguf_file::Value, name: &str) -> Result<Vec<String>> {
    let arr = v
        .to_vec()
        .with_context(|| format!("`{name}` is not an array"))?;
    arr.iter()
        .map(|v| {
            v.to_string()
                .map(|s| s.to_string())
                .with_context(|| format!("`{name}` element is not a string: {v:?}"))
        })
        .collect()
}

fn merges_from_value(v: &gguf_file::Value) -> Result<Vec<(String, String)>> {
    value_to_string_array(v, "tokenizer.ggml.merges")?

View on GitHub (pinned to d5fee525bf)

Solutions

  1. Re-export/regenerate the GGUF with a converter that writes numeric token types/ids (e.g. current llama.cpp convert script)
  2. Inspect the GGUF metadata (gguf_file::Content) and fix the offending key to a numeric value
  3. Bypass the strict conversion by reading the metadata yourself and passing values directly to Tokenizer::new
Defensive patterns

Strategy: try-catch

Validate before calling

let v = ct.metadata.get("tokenizer.ggml.token_type")
    .ok_or_else(|| anyhow::anyhow!("missing token_type"))?;
if !matches!(v, GgmlDType-numeric(_) if true) { /* inspect: ensure it's a gguf_file::Value::U*/ }

Type guard

fn is_numeric_gguf_value(v: &gguf_file::Value) -> bool {
    matches!(v,
        gguf_file::Value::U8(_) | gguf_file::Value::U16(_) | gguf_file::Value::U32(_)
        | gguf_file::Value::I16(_) | gguf_file::Value::I32(_)
        | gguf_file::Value::U64(_) | gguf_file::Value::I64(_))
}

Try / catch

match Tokenizer::from_gguf(&ct) {
    Ok(t) => t,
    Err(e) if e.to_string().contains("expected numeric value") => {
        return Err(anyhow::anyhow!("GGUF tokenizer metadata malformed; re-export the file: {e}"))
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Loading a GGUF file whose tokenizer metadata contains a non-numeric value where a token type or token id is required, via Tokenizer::from_gguf / from_gguf converters calling gguf_value_to_u32.

Common situations: GGUF files produced by converters that wrote token_type as a string (e.g. "1") or stored ids in an array; hand-edited or malformed GGUF metadata; unsupported exporter versions.

Related errors


AI-assisted analysis of huggingface/candle@d5fee525bf (2026-09-02). Data as JSON: /api/errors/1ca10c2f25961abb. Report an issue: GitHub.