Hmbown/CodeWhale · info

event recovery buffer fits u64

Error message

event recovery buffer fits u64

What it means

Panic from `u64::try_from(buffer.len())` when reading the event recovery log backwards in 8 KiB chunks. `buffer` is a fixed `[0_u8; 8*1024]`, so its length always fits in u64; the expect documents and asserts that conversion cannot fail on any supported platform.

Solutions

  1. No action needed for the fixed-size buffer; leave the expect as a documented invariant
  2. If the buffer ever becomes dynamic, add a length check before the try_from
Defensive patterns

Strategy: validation

Validate before calling

// buffer is [0u8; 8192]; u64::try_from(8192usize) always Ok — no pre-check needed

Prevention

When it happens

Trigger: Effectively unreachable: would require `buffer.len()` to exceed `u64::MAX`, impossible for a fixed 8192-byte stack buffer. Only a change of `buffer` to a huge heap allocation on a hypothetical >u64 platform could trigger it.

Common situations: A refactor replacing the fixed stack buffer with a dynamically sized one on a platform where usize exceeds u64 (no current target).

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/747c2d170dc689df. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/runtime_threads.rs:14020

    let len = file
        .metadata()
        .with_context(|| format!("Failed to inspect {}", path.display()))?
        .len();
    if len == 0 {
        return Ok(());
    }

    file.seek(SeekFrom::End(-1))?;
    let mut last = [0_u8; 1];
    file.read_exact(&mut last)?;
    if last[0] == b'\n' {
        return Ok(());
    }

    let mut search_end = len;
    let mut truncate_at = 0_u64;
    let mut buffer = [0_u8; 8 * 1024];
    let buffer_len = u64::try_from(buffer.len()).expect("event recovery buffer fits u64");
    while search_end > 0 {
        let chunk_len = usize::try_from(search_end.min(buffer_len))
            .expect("event recovery chunk length fits usize");
        let chunk_len_u64 = u64::try_from(chunk_len).expect("event recovery chunk length fits u64");
        let chunk_start = search_end - chunk_len_u64;
        file.seek(SeekFrom::Start(chunk_start))?;
        file.read_exact(&mut buffer[..chunk_len])?;
        if let Some(index) = buffer[..chunk_len].iter().rposition(|byte| *byte == b'\n') {
            truncate_at = chunk_start
                + u64::try_from(index).expect("event recovery newline index fits u64")
                + 1;
            break;
        }
        search_end = chunk_start;
    }

    file.set_len(truncate_at)
        .with_context(|| format!("Failed to truncate torn tail in {}", path.display()))?;

View on GitHub (pinned to 73e0f67d83)