Return errors instead of panicking in fallible functions - #10755
Open
emilk wants to merge 8 commits into
Open
Conversation
emilk
commented
Aug 19, 2026
emilk
marked this pull request as ready for review
August 19, 2026 13:34
emilk
marked this pull request as draft
August 19, 2026 13:37
These functions already return `Result`, but reported some failures by panicking. Several are reachable from untrusted input, where a panic is a denial of service rather than a bug report: * `b64_decode` panicked on invalid base64 in the input array * `read_record_batch` asserted on the variadic buffer counts declared by the IPC message, and `FileReaderBuilder::build` unwrapped footer metadata whose key or value may be absent * `Decoder::flush` (arrow-json) unwrapped a malformed tape * `FFI_ArrowSchema::metadata` unwrapped lengths supplied by the producer, and preallocated a `HashMap` for an entry count it had not checked * `ArrayData::validate_values` had `unreachable!()` arms for dictionary key and run end types, in a function whose whole job is to report bad data * `concat_elements_bytes` and `concat_elements_utf8_many` unwrapped the offset conversion, so a long enough concatenation panicked * `ColumnReader::skip_records` asserted on a page's record count * `get_row_group_column_bloom_filter` (sync and async) unwrapped the Bloom filter offsets, and subtracted them without checking * `ArrowColumnWriter::close` and `SerializedFileWriter::next_row_group` unwrapped on shared state and on overflow * the three `try_new_from_builder` dictionary builders unwrapped on a shared key buffer * the Flight SQL client unwrapped a truncated or unexpected server response * `garbage_collect_dictionary` unwrapped the new dictionary key * `data_type_from_json`, `field_from_json`, `ArrowFile::read_batch(es)` and `open_json_file` unwrapped malformed JSON Adds tests for the base64 and `validate_values` error paths. The remaining panics are documented or removed separately; this covers only the functions that could report the failure and did not. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
emilk
force-pushed
the
emilk/missing-panics-doc
branch
from
August 19, 2026 14:51
3434897 to
35097d8
Compare
This was referenced Aug 19, 2026
alamb
reviewed
Aug 19, 2026
`new_keys` comes from `try_unary` on a locally owned array, and the `drop` just above releases the null buffer it shared with `source_keys`, so `into_builder` holds the only reference and cannot fail. Word the error as an internal one, so a reader does not go looking for the input that triggers it. The old wording also blamed the source builder, when the buffer in question is the freshly derived one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
One variadic buffer count is consumed per `BinaryView` or `Utf8View` column in the schema, so a leftover count means the message describes more view columns than the schema has. Say that, rather than reporting the symptom. This also matches how `create_array` reports the opposite case, too few counts. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`ArrayData::validate_values` is public and can be called without `validate()` having checked the buffer and child counts first, so the `buffers[i]` and `child_data[i]` indexing panicked on bad data instead of reporting it. Add `buffer_at` and `child_at` accessors that return an error, and use them on every path `validate_values` can reach. `check_bounds` now goes through `typed_buffer`, which performs the same size check it used to assert on. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The number of variadic buffers for a `BinaryView` or `Utf8View` column
was taken from the IPC message and used unchecked. A negative count made
`create_primitive_array` index a buffer slice that was too short, so a
crafted message panicked instead of being rejected:
index out of bounds: the len is 0 but the index is 0
The same count is used by `skip_field` for columns a projection leaves
out, where `skip_buffer` unwrapped the exhausted buffer iterator.
Check the count against the buffers the message actually has, and let
`skip_buffer` report the mismatch instead of unwrapping.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`read_records` and `skip_records` guard the same invariant with the same code, but only `skip_records` reported it. Share one check between them, and say which invariant was broken. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`garbage_collect_dictionary` built a bespoke `ComputeError` for a key that does not fit its type. `ArrowError::DictionaryKeyOverflowError` is what the rest of the crate reports for exactly that, including the call a few lines below, so use it. `ArrowColumnWriter::close` documented an error the caller cannot cause and did not mention the poisoned lock, which is the one that can happen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
# Conflicts: # arrow-string/src/concat_elements.rs
emilk
marked this pull request as ready for review
August 20, 2026 11:34
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Which issue does this PR close?
Rationale for this change
While clearing
clippy::missing_panics_doc, a pattern turned up: functions thatalready return
Result, but report some failures by panicking. Several arereachable from untrusted input, so the panic is a denial of service rather than a
bug report.
Documenting those panics would normalise them, so this returns errors instead.
This is one of four PRs splitting up the work.
unwraps #10759 - remove unreachable panics#[expect(clippy::missing_panics_doc)]#10761 -#[expect]the unreachable ones, so the lint can be turned onWhat changes are included in this PR?
Functions that could report the failure and did not.
Are these changes tested?
Covered by the existing tests, plus new tests for the
b64_decodeandArrayData::validate_valueserror paths.Are there any user-facing changes?
No API changes. Some calls that used to panic now return an
Err, which is thepoint of the PR.