EpicGames/lore · warning

hex was not valid utf8

Error message

hex was not valid utf8

What it means

After hex-encoding into dst, to_hex_str converts dst to &str with str::from_utf8 and panics if the bytes are not valid UTF-8. Since hex::encode_to_slice only writes ASCII hex digits, this expect is unreachable when the encode step succeeded on the intended buffer; it fires if dst already contained non-UTF-8 bytes that encode_to_slice did not overwrite (partial write) or is otherwise corrupted.

Solutions

  1. Treat this panic as a bug report: verify dst is zero-initialized before calling to_hex_str
  2. Ensure the preceding 'hex encode failed' panic is not being masked; fix the buffer length first
  3. Always pass a freshly allocated buffer rather than a reused one
  4. If you control the code, prefer hex::encode to return an owned String and remove the two expects

Example fix

// before
let mut buf = reused_scratch; // may hold stale non-UTF8 bytes
let s = to_hex_str(src, &mut buf);
// after
let mut buf = vec![0u8; src.len() * 2]; // fresh, zeroed
let s = to_hex_str(src, &mut buf);
Defensive patterns

Strategy: validation

Validate before calling

fn dst_clean(dst: &[u8]) -> bool { dst.iter().all(|&b| b == 0) } // call on a fresh buffer before to_hex_str

Type guard

fn is_ascii_hex(buf: &[u8]) -> bool { buf.iter().all(|b| b.is_ascii_hexdigit()) }

Try / catch

match std::panic::catch_unwind(|| to_hex_str(src, &mut buf)) {
    Ok(s) => s,
    Err(_) => { /* treat as corruption bug; regenerate buffer and retry once */ }
}

Prevention

When it happens

Trigger: Effectively only when the preceding hex::encode_to_slice did not fill the whole buffer (e.g. panic-free misuse, custom hex versions) leaving stale non-UTF-8 bytes in dst, or if encode wrote nothing due to empty/edge-case misuse combined with pre-filled invalid bytes.

Common situations: Buffer reuse across calls where a prior failed encode left garbage, or a vendored/patched hex crate whose error paths differ from expectations. In practice developers hit this via the sibling 'hex encode failed' panic; this one indicates deeper memory/buffer corruption.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of EpicGames/lore@074eb0b0d1 (2026-09-13). Data as JSON: /api/errors/84f9aaedb536f75e. Report an issue: GitHub.

Appendix: source

Thrown at lore-revision/src/util.rs:24

pub mod encoding;
pub mod fs;
pub mod inflight;
pub mod path;
pub mod serde;
pub mod task_queue;
pub mod time;
pub mod url;

/// Provides a mechanism for converting data to a hex `&str` without unnecessary allocations.
/// Note: the `dst` parameter must be passed in in order to give us something to which we can tie
///     the lifetime of the returned &str.
#[inline]
pub fn to_hex_str<'a>(src: &[u8], dst: &'a mut [u8]) -> &'a str {
    debug_assert_eq!(dst.len(), src.len() * 2);

    // These should never fail, but if it does, we'd rather panic than use a default value
    hex::encode_to_slice(src, dst).expect("hex encode failed");
    std::str::from_utf8(dst).expect("hex was not valid utf8")
}

View on GitHub (pinned to 074eb0b0d1)