BoundaryML/baml · error · io::Error

invalid profiling usage ledger

Error message

invalid profiling usage ledger

What it means

read_usage_state loads the store's `usage.state` ledger and requires it to be exactly USAGE_STATE_BYTES long and to begin with the 8-byte USAGE_MAGIC. If the length or magic check fails, it raises InvalidData 'invalid profiling usage ledger' because the file is not a ledger this store version wrote.

Source

Thrown at baml_language/crates/bex_prof_store/src/prof/backend/store.rs:1657

                    io::ErrorKind::InvalidData,
                    "profiling store contains an unsupported file type",
                ));
            }
        }
        Ok(())
    }

    let mut total = USAGE_STATE_BYTES;
    scan(root, root, &mut total)?;
    Ok(total)
}

fn read_usage_state(root: &Path) -> io::Result<u64> {
    let usage_state_len = usize::try_from(USAGE_STATE_BYTES).expect("fixed usage state fits usize");
    let mut bytes = Vec::with_capacity(usage_state_len);
    File::open(root.join("usage.state"))?.read_to_end(&mut bytes)?;
    if bytes.len() != usage_state_len || &bytes[..8] != USAGE_MAGIC {
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            "invalid profiling usage ledger",
        ));
    }
    let expected: [u8; 32] = Sha256::digest(&bytes[..16]).into();
    if bytes[16..] != expected {
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            "profiling usage ledger checksum mismatch",
        ));
    }
    Ok(u64::from_be_bytes(
        bytes[8..16].try_into().expect("fixed-width usage"),
    ))
}

fn write_usage_state(root: &Path, usage: u64, platform: &dyn StorePlatform) -> io::Result<()> {
    let usage_state_len = usize::try_from(USAGE_STATE_BYTES).expect("fixed usage state fits usize");

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Delete usage.state and let the store rebuild/reinitialize it (usage will be re-estimated from the segment scan).
  2. Restore usage.state from a backup of the profiling store taken while the process was quiescent.
  3. Verify you are opening the store with the same library version that created it (ledger layout/magic may differ across versions).
  4. Recreate the profiling store directory if its contents are expendable.

Example fix

// shell
// before: usage.state truncated/corrupt
// after
rm <store-root>/usage.state  # store reinitializes the ledger on next open
Defensive patterns

Strategy: validation

Validate before calling

let path = root.join("usage.state");
if !path.exists() || fs::metadata(&path)?.len() != USAGE_STATE_BYTES as u64 {
    // ledger missing or wrong size: delete it and let the store reinitialize
    let _ = fs::remove_file(&path);
}

Try / catch

match read_usage_state(&root) {
    Ok(usage) => usage,
    Err(e) if e.kind() == io::ErrorKind::InvalidData && e.to_string().contains("invalid profiling usage ledger") => {
        let _ = fs::remove_file(root.join("usage.state"));
        rebuild_usage_from_segments(&root)
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Opening/reading usage accounting when usage.state is missing bytes (truncated/empty), longer than expected, was created by a different tool/version, or starts with bytes other than USAGE_MAGIC.

Common situations: Manual edits to usage.state; crash during the first write leaving a zero-length file; store created by an older/newer version with a different layout; copying a partial file; a user placing an unrelated file named usage.state in the store root.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/d8cffb2e902cae8d. Report an issue: GitHub.