pola-rs/polars · error
length to fit in `usize`
Error message
length to fit in `usize`
What it means
When importing an array over the Arrow C Data Interface (crates/polars-arrow/src/ffi/array.rs), `ArrowArray.length` is an `i64` per the spec. `create_bitmap` does `array.length.try_into().expect("length to fit in `usize`")`. On 64-bit targets this only fails for negative lengths; on 32-bit targets also for lengths above u32::MAX. A negative/garbage length from the foreign producer is treated as an unrecoverable invariant violation and panics.
Source
Thrown at crates/polars-arrow/src/ffi/array.rs:328
Ok(Buffer::from(v))
}
}
/// returns the buffer `i` of `array` interpreted as a [`Bitmap`].
/// # Safety
/// This function is safe iff:
/// * the buffer at position `index` is valid for the declared length
/// * the buffers' pointer is not mutable for the lifetime of `owner`
unsafe fn create_bitmap(
array: &ArrowArray,
dtype: &ArrowDataType,
owner: InternalArrowArray,
index: usize,
// if this is the validity bitmap
// we can use the null count directly
is_validity: bool,
) -> PolarsResult<Bitmap> {
let len: usize = array.length.try_into().expect("length to fit in `usize`");
if len == 0 {
// Zero-length arrays might have invalid pointers for zero-length slices in Rust,
// so this is more than just an optimization.
return Ok(Bitmap::new());
}
let ptr = get_buffer_ptr(array, dtype, index)?;
// Pointer of u8 has alignment 1, so we don't have to check alignment.
let offset: usize = array.offset.try_into().expect("offset to fit in `usize`");
let bytes_len = bytes_for(offset + len);
let slice = core::slice::from_raw_parts(ptr, bytes_len);
let storage = SharedStorage::from_slice_with_owner(slice, owner);
let null_count = if is_validity {
Some(array.null_count())
} else {
None
};View on GitHub (pinned to 9b5d73fd00)
Solutions
- Fix the producer: initialize every ArrowArray field per the C data interface spec (length >= 0, sane offset, release callback set).
- Validate the struct in the producer/exporter before handing it to Rust.
- Wrap `from_ffi` in `std::panic::catch_unwind` at the interop boundary and report which batch failed instead of crashing the process.
- If on a 32-bit target with legitimately huge arrays, move to 64-bit — lengths that don't fit usize can't be handled at all.
Example fix
// before (Rust consumer)
let array = unsafe { from_ffi(imported, owner) }?; // panics if producer sent negative length
// after
let result = std::panic::catch_unwind(|| unsafe { from_ffi(imported, owner) });
let array = result.map_err(|_| polars_err!(ComputeError: "foreign producer exported an ArrowArray with invalid length"))??; Defensive patterns
Strategy: try-catch
Validate before calling
// ArrowArray fields are pub(super); validate on the producer side before export: // C/other-language producer: assert(array->length >= 0 && array->offset >= 0); // and (on 32-bit) assert((uint64_t)array->length <= UINT32_MAX);
Try / catch
let array = std::panic::catch_unwind(|| unsafe { polars_arrow::ffi::from_ffi(imported, owner) })
.map_err(|_| polars_err!(ComputeError: "foreign ArrowArray has invalid length; check producer"))?; Prevention
- Fully initialize every ArrowArray field on export (length, offset, null_count, buffers, release).
- Pin the same major version of the C Data Interface on both sides of the boundary.
- Add producer-side assertions on length/offset before invoking the consumer.
- Keep catch_unwind only at the interop boundary, and log which batch triggered it.
When it happens
Trigger: `from_ffi`/`try_from_ffi` on an `ArrowArray` whose `length` field is negative (uninitialized or corrupted C struct) or, on 32-bit builds, larger than usize. The panic fires while building the validity/offset bitmap for any array with non-zero length, including validity-only paths.
Common situations: FFI interop with C/C++/Golang/Java producers: passing an ArrowArray struct that wasn't fully initialized (e.g. zeroing only some fields, or exporting via a stale/mismatched ABI version), or memory corruption/missing owner lifetime on the producer side. Rare in correct pyarrow-based flows, more common in hand-written C bridges.
Related errors
- offset to fit in `usize`
- Offset to fit in `usize`
- The external API has a non-utf8 as format
- not implemented
- The schema declaration does not match the deserialization
AI-assisted analysis of pola-rs/polars@9b5d73fd00 (2026-08-19).
Data as JSON: /api/errors/63795a777278ec44.
Report an issue: GitHub.