fix: stop try_ functions from panicking - #10730
Conversation
| NullBuffer::union(a.logical_nulls().as_ref(), b.logical_nulls().as_ref()).unwrap(); | ||
| // `null_count` is a physical count, so it can be non-zero for arrays that | ||
| // have no logical nulls at all: | ||
| let Some(nulls) = NullBuffer::union(a.logical_nulls().as_ref(), b.logical_nulls().as_ref()) |
There was a problem hiding this comment.
do we have a reproduction for this? im struggling to conceptualize a case where we physically have nulls but logically dont have nulls 🤔
There was a problem hiding this comment.
One example is RunArray… except the if above was wrong, and was checking null_count instead of is_nullable. Fixed in 97f3028
There was a problem hiding this comment.
This is an actual bug fix now btw - test_try_binary_run_array_logical_nulls fails on main with
assertion `left == right` failed
left: [11, 1, 31]
right: [11, null, 31]
should I split out the bug fix into its own PR?
There was a problem hiding this comment.
yeah we should split this into a separate PR
There was a problem hiding this comment.
4659507 to
97f3028
Compare
|
run benchmark mutable_array |
This comment was marked as duplicate.
This comment was marked as duplicate.
|
🤖 Arrow criterion benchmark completed (GKE) | trigger Instance: Comparing emilk/fix-panicking-try-fns (97f3028) to bb1e6cd (merge-base) diff Run configurationrun benchmark mutable_arrayCPU Details (lscpu)Details
Resource Usagebase (merge-base)
branch
File an issue against this benchmark runner |
A `try_` function that returns a `Result` but still panics is the worst of both worlds. Turn those panics into errors: * `FFI_ArrowSchema::try_new`: an interior nul byte in `format` was an `unwrap`. It now returns `ArrowError::CDataInterface`, and the format is converted before the children are leaked, so the error path no longer leaks memory. * `MutableArrayData::try_extend`: validate the source array index and the `start..end` range. `end < start` used to underflow. * `MutableArrayData::try_extend_nulls`: return an error instead of panicking when the builder has no null buffer. * `VariantArray::try_value`: return an error for an out of bounds index and for a row with conflicting `value` and `typed_value`. * `try_binary`: `NullBuffer::union` returns `None` when neither input has logical nulls, which is possible even when `null_count() > 0`. Fall back to the no-nulls path instead of unwrapping. `MutableBuffer::try_from_trusted_len_iter` still panics on a bad `size_hint`: that is part of its `unsafe` contract, and the docs now say so. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Review feedback: hovering the function should show the reasons, without having to open the `try_` version's docs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Review feedback. `FFI_ArrowSchema::try_new` had the reason in prose, `try_binary` used `# Error`, and `try_from_trusted_len_iter` did not say what its `Err` meant. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
97f3028 to
b0c7b97
Compare
|
Which issue does this PR close?
# Panicssections across the workspace #10656Rationale for this change
A
try_function that returns aResultbut still panics is the worst of both worlds: the caller writes error handling and gets a panic anyway.What changes are included in this PR?
FFI_ArrowSchema::try_new: an interior nul byte informatwas anunwrap, and the error path leaked the children.MutableArrayData::try_extend: validates the array index and thestart..endrange, which used to underflow.MutableArrayData::try_extend_nulls: errors instead of panicking when there is no null buffer.VariantArray::try_value: errors on an out of bounds index, and on conflictingvalue/typed_value.MutableBuffer::try_from_trusted_len_iterstill panics on a badsize_hint: that is part of itsunsafecontract, and the docs now say so.Are these changes tested?
Yes, a test per error path.
Are there any user-facing changes?
Panics turn into errors.
MutableArrayData::extend/extend_nullsstill panic as before.