huggingface/candle · error

not a f32 {v:?}

Error message

not a f32 {v:?}

What it means

This error is thrown by Value::to_f32 in candle's GGUF reader when you ask a GGUF metadata value to be an f32 but the Value enum actually holds a different variant (e.g. String, U32, Array). GGUF metadata values are tagged unions, so conversion only succeeds when the variant matches exactly; candle bails instead of coercing. The {v:?} in the message prints the actual variant that was found.

Source

Thrown at candle-core/src/quantized/gguf_file.rs:287

            Self::U8(v) => Ok(*v as u64),
            Self::U16(v) => Ok(*v as u64),
            Self::U32(v) => Ok(*v as u64),
            Self::Bool(v) => Ok(*v as u64),
            v => crate::bail!("not a u64 or upcastable to u64 {v:?}"),
        }
    }

    pub fn to_i64(&self) -> Result<i64> {
        match self {
            Self::I64(v) => Ok(*v),
            v => crate::bail!("not a i64 {v:?}"),
        }
    }

    pub fn to_f32(&self) -> Result<f32> {
        match self {
            Self::F32(v) => Ok(*v),
            v => crate::bail!("not a f32 {v:?}"),
        }
    }

    pub fn to_f64(&self) -> Result<f64> {
        match self {
            Self::F64(v) => Ok(*v),
            v => crate::bail!("not a f64 {v:?}"),
        }
    }

    pub fn to_bool(&self) -> Result<bool> {
        match self {
            Self::Bool(v) => Ok(*v),
            v => crate::bail!("not a bool {v:?}"),
        }
    }

    pub fn to_vec(&self) -> Result<&Vec<Value>> {

View on GitHub (pinned to d5fee525bf)

Solutions

  1. Call .to_u32()/.to_u64() instead if the field was written as an integer (most GGUF numeric metadata is u32).
  2. Inspect the error's {v:?} payload to see the real variant and use the matching accessor (to_f64, to_string, to_vec, ...).
  3. Match on the Value enum directly and handle multiple variants instead of using a fixed accessor.
  4. Fix the GGUF writing side to emit ValueType::F32 if the field genuinely should be a float.

Example fix

// before
let emb_len = value.to_f32()?;
// after
let emb_len = match value {
    gguf_file::Value::U32(v) => v as f32,
    gguf_file::Value::F32(v) => v,
    other => candle_core::bail!("unexpected embedding_length {other:?}"),
};
Defensive patterns

Strategy: type-guard

Validate before calling

fn is_f32(v: &gguf_file::Value) -> bool { matches!(v, gguf_file::Value::F32(_)) }
if !is_f32(value) { bail!("expected f32 metadata, got {value:?}"); }

Type guard

fn as_f32(v: &gguf_file::Value) -> Option<f32> {
    if let gguf_file::Value::F32(x) = v { Some(*x) } else { None }
}

Try / catch

let f = match value.to_f32() {
    Ok(f) => f,
    Err(e) => { eprintln!("gguf f32 field mismatch: {e}"); return fallback_default; }
};

Prevention

When it happens

Trigger: Calling .to_f32() on a Value read from a GGUF file whose metadata entry is not ValueType::F32, e.g. a model's 'embedding_length' stored as u32 (the common case) or a string field like 'general.architecture'.

Common situations: Hand-parsing GGUF headers with gguf_file::Content::read and assuming numeric fields are f32 when GGUF spec defaults them to u32/u64; reading a file produced by a converter that wrote f64 or u32; typos in field names picking up the wrong metadata entry.

Related errors


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