windmill-labs/windmill · error

hex string did not decode to an u64: {s}

Error message

hex string did not decode to an u64: {s}

What it means

to_i64 decodes a hex string expected to encode a 64-bit big-endian integer. If hex::decode succeeds but yields fewer than 8 bytes, the string cannot represent a u64 and this error is returned (note the message says u64 although the function returns i64).

Source

Thrown at backend/windmill-types/src/scripts.rs:738

    let languages: Vec<ScriptLang> = s
        .split(",")
        .map(ScriptLang::from_str)
        .try_collect()
        .map_err(|e: anyhow::Error| serde::de::Error::custom(e.to_string()))?;

    let languages = if languages.is_empty() {
        None
    } else {
        Some(languages)
    };

    Ok(languages)
}

pub fn to_i64(s: &str) -> anyhow::Result<i64> {
    let v = hex::decode(s)?;
    if v.len() < 8 {
        return Err(anyhow::anyhow!("hex string did not decode to an u64: {s}",));
    }
    let nb: u64 = u64::from_be_bytes(
        v[0..8]
            .try_into()
            .map_err(|_| hex::FromHexError::InvalidStringLength)?,
    );
    Ok(nb as i64)
}

pub fn to_hex_string(i: &i64) -> String {
    hex::encode(i.to_be_bytes())
}

#[derive(Deserialize, Serialize)]
pub struct HubScript {
    pub content: String,
    pub lockfile: Option<String>,
    pub language: ScriptLang,

View on GitHub (pinned to e474e8803c)

Solutions

  1. Ensure the hex string encodes a full 8-byte value (16 hex characters)
  2. Regenerate the value at the source instead of truncating it
  3. Verify hex::decode succeeded (invalid chars would fail earlier with a hex error)
  4. Also confirm the string has no `0x` prefix, which decode rejects

Example fix

// before
let n = windmill::to_i64("abcd")?; // 2 bytes
// after
let n = windmill::to_i64("000000000000abcd")?; // 8 bytes
Defensive patterns

Strategy: validation

Validate before calling

def ensure_u64_hex(s: str) -> str:
    body = s[2:] if s.startswith("0x") else s
    if len(body) != 16 or any(c not in "0123456789abcdefABCDEF" for c in body):
        raise ValueError(f"expected 16 hex chars encoding a u64, got {s!r}")
    return body.lower()

Try / catch

match windmill_types::scripts::to_i64(s) {
    Err(e) if e.to_string().contains("hex string did not decode") => {
        eprintln!("value {s} is not a full 8-byte hex encoding");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Passing a hex string shorter than 16 hex chars (fewer than 8 bytes) to to_i64 — e.g. a truncated hash prefix or a malformed encoded integer.

Common situations: Storing/truncating encoded values in the database; hand-constructed hex ids; mismatched encoding between writer and reader.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/dd714e336d995592. Report an issue: GitHub.