run-llama/liteparse · error · std::io::Error
invalid RGB buffer length for
Error message
invalid RGB buffer length for {width}x{height}: expected {expected_len} bytes, got {} What it means
rgb_image requires the byte slice to contain exactly width * height * 3 bytes (one RGB triple per pixel). When image_data.len() differs from the expected length, the buffer and the declared dimensions disagree, so the call is rejected with this InvalidInput error naming both expected and actual sizes. This is a strict contract check before constructing the RgbImage.
Solutions
- Convert the buffer to strict 3-bytes-per-pixel RGB before calling (drop the alpha channel, remove row stride/padding).
- Recompute width/height from the actual buffer (len/3, with a known aspect) so they match.
- Ensure the dimensions and the byte buffer come from the same decoded image.
Example fix
// before: RGBA buffer passed as RGB let rgba = decoded.to_rgba8(); ocr.recognize_sync(rgba.as_raw(), decoded.width(), decoded.height())?; // after: convert to RGB first let rgb = DynamicImage::ImageRgba8(decoded.to_rgba8()).to_rgb8(); ocr.recognize_sync(rgb.as_raw(), rgb.width(), rgb.height())?;
Defensive patterns
Strategy: validation
Validate before calling
// Rust: assert RGB (3 bytes/pixel) buffer length matches dims
fn rgb_len_ok(data: &[u8], w: u32, h: u32) -> bool {
data.len() == w as usize * h as usize * 3
} Type guard
fn as_exact_rgb(data: &[u8], w: u32, h: u32)
-> Option<&[u8]>
{
let expected = (w as usize).checked_mul(h as usize)?.checked_mul(3)?;
(data.len() == expected).then_some(data)
} Prevention
- Always convert RGBA/grayscale buffers to strict RGB before OCR
- Derive width/height and bytes from the same decoded image object
- Strip row stride/padding before passing raw buffers
When it happens
Trigger: Calling the OCR recognize path with a buffer whose length does not match width*height*3 — e.g. passing RGBA data (4 bytes/pixel) as RGB, passing grayscale data, or passing dimensions from a different image than the buffer.
Common situations: Mixing up RGBA and RGB buffers when piping decoded image data to OCR; OCR servers returning raw buffers with stride/padding; copying dimensions from one decoded image and bytes from another.
Related errors
- invalid zero-sized RGB image
- RGB image dimensions overflow
- failed to construct RGB image from
- no data on stdin (input `-` expects a document piped in…
- no data on stdin (input `-` expects a document piped in…
AI-assisted analysis of run-llama/liteparse@22d2dd8cd7 (2026-09-08).
Data as JSON: /api/errors/a4845a7dc8604ab5.
Report an issue: GitHub.
Appendix: source
Thrown at crates/liteparse/src/ocr/oar.rs:277
if width == 0 || height == 0 {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!("invalid zero-sized RGB image: {width}x{height}"),
));
}
let expected_len = (width as usize)
.checked_mul(height as usize)
.and_then(|pixels| pixels.checked_mul(3))
.ok_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidInput,
format!("RGB image dimensions overflow: {width}x{height}"),
)
})?;
if image_data.len() != expected_len {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!(
"invalid RGB buffer length for {width}x{height}: expected {expected_len} bytes, got {}",
image_data.len()
),
));
}
image::RgbImage::from_raw(width, height, image_data.to_vec()).ok_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidInput,
format!("failed to construct RGB image from {width}x{height} buffer"),
)
})
}
fn region_to_result(region: oar_ocr::oarocr::TextRegion) -> Option<OcrResult> {
let text = region.text?.trim().to_owned();View on GitHub (pinned to 22d2dd8cd7)