huggingface/candle · error

not a string {v:?}

Error message

not a string {v:?}

What it means

Value::to_string throws this when the GGUF metadata value is not the String variant. GGUF strings are a distinct tagged type (with their own length prefix), and candle will not stringify other variants implicitly. The Debug form of the found value appears in the message.

Source

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

    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>> {
        match self {
            Self::Array(v) => Ok(v),
            v => crate::bail!("not a vec {v:?}"),
        }
    }

    pub fn to_string(&self) -> Result<&String> {
        match self {
            Self::String(v) => Ok(v),
            v => crate::bail!("not a string {v:?}"),
        }
    }

    fn read<R: std::io::Read + std::io::Seek>(
        reader: &mut R,
        value_type: ValueType,
        magic: &VersionedMagic,
        depth: usize,
        file_size: u64,
    ) -> Result<Self> {
        if depth > GGUF_MAX_VALUE_DEPTH {
            crate::bail!("gguf: value nesting depth exceeds max {GGUF_MAX_VALUE_DEPTH}")
        }
        let v = match value_type {
            ValueType::U8 => Self::U8(reader.read_u8()?),
            ValueType::I8 => Self::I8(reader.read_i8()?),
            ValueType::U16 => Self::U16(reader.read_u16::<LittleEndian>()?),
            ValueType::I16 => Self::I16(reader.read_i16::<LittleEndian>()?),

View on GitHub (pinned to d5fee525bf)

Solutions

  1. Read the actual variant from the {v:?} output and use its accessor (to_u32, to_vec, ...).
  2. Verify the metadata key name — a misspelled or renamed key may resolve to a differently typed entry.
  3. Match on the Value enum and convert manually (e.g. format integer variants if a string display is wanted).
  4. Fix the GGUF producer to write the field with ValueType::String.

Example fix

// before
let arch = value.to_string()?;
// after
let arch = match value {
    gguf_file::Value::String(s) => s.as_str(),
    other => candle_core::bail!("general.architecture is not a string: {other:?}"),
};
Defensive patterns

Strategy: type-guard

Validate before calling

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

Type guard

fn as_str(v: &gguf_file::Value) -> Option<&str> {
    if let gguf_file::Value::String(s) = v { Some(s.as_str()) } else { None }
}

Try / catch

let s = match value.to_string() {
    Ok(s) => s.clone(),
    Err(e) => { eprintln!("not a string: {e}"); return Err(e.into()); }
};

Prevention

When it happens

Trigger: Calling .to_string() on a metadata entry stored as U8/U32/I64/Array etc., e.g. expecting 'general.architecture' to be a string but grabbing a numeric or array-valued key instead.

Common situations: Wrong metadata key lookup returning a numeric field; assuming byte-array tokens are strings when they are Arrays of u32; using to_string() on Value out of habit because Rust's ToString exists.

Related errors


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