huggingface/candle · error
not a string
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.
Solutions
- Read the actual variant from the {v:?} output and use its accessor (to_u32, to_vec, ...).
- Verify the metadata key name — a misspelled or renamed key may resolve to a differently typed entry.
- Match on the Value enum and convert manually (e.g. format integer variants if a string display is wanted).
- 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
- Don't confuse Rust's ToString with GGUF's to_string (which asserts the String variant)
- Print the Debug value on mismatch to discover the actual variant
- Lock metadata key names against the GGUF spec for the architecture
- Fail fast with a clear message instead of silently coercing types
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.
Appendix: 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)