Skip to content

fix: return an error instead of aborting in repeat for huge LargeUtf8 results - #26957

Merged
mbutrovich merged 5 commits into
apache:mainfrom
shahwazreza:fix-repeat-large-utf8-abort
Nov 5, 2026
Merged

mbutrovich merged 5 commits into
apache:mainfrom
shahwazreza:fix-repeat-large-utf8-abort

Conversation

@shahwazreza

@shahwazreza shahwazreza commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Rationale for this change

repeat on a LargeUtf8 string with a huge count, e.g. repeat(arrow_cast('a', 'LargeUtf8'), 1152921504606846976), aborts the process (scalar case) or panics (array case) instead of returning an error. Utf8 and Utf8View already error above i32::MAX bytes, but LargeUtf8 was capped at i64::MAX, which is way past anything that can actually be allocated.

What changes are included in this PR?

LargeUtf8 now uses a fixed cap of u32::MAX bytes (LARGE_UTF8_MAX_SIZE). In the array path the cap applies to each value and to the total size of the output, since the builder allocates the whole output up front. My first version only checked each value, so lots of rows could still add up to an allocation that panics. The second commit fixes that.

The issue asked whether to use a cap or fallible allocation. I went with a cap because the builder has no fallible way to allocate, and changing that would be a bigger separate change. A cap also behaves the same way Utf8 already does.

u32::MAX matches DuckDB's string size limit and still lets LargeUtf8 go past the Utf8 limit. Happy to change it, e.g. to Postgres' 1 GB, if it is preferred.

This doesn't help when an allocation under the cap succeeds and then fails later because of overcommit, same as the issue says.

What is the testing strategy for this PR?

Unit tests in repeat.rs:

  • scalar LargeUtf8 with a count of 1 << 60 (used to abort the test process)
  • array LargeUtf8 with a count of 1 << 60 (used to panic)
  • array with two rows of ~3 GB each: fine on their own, over the cap together

Are there any user-facing changes?

repeat returns an error for LargeUtf8 results over u32::MAX bytes instead of trying to allocate them.

…f8 results

`repeat` capped LargeUtf8 results at i64::MAX bytes, which admits sizes
no allocation can satisfy, so the process aborted or panicked instead of
returning an error. Cap LargeUtf8 results at u32::MAX bytes in both the
scalar and array paths.

Closes apache#26948
@github-actions github-actions Bot added the functions Changes to functions implementation label Oct 30, 2026
The per-row cap alone still let many rows add up to an allocation no
system can satisfy, which panicked in the Arrow buffer instead of
returning an error.

@mbutrovich mbutrovich left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @shahwazreza for the fix, and for catching the total-size case in the second commit.

Co-authored-by: Matt Butrovich <6855576+mbutrovich@users.noreply.github.com>

@mbutrovich mbutrovich left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR @shahwazreza! Approved pending CI.

@shahwazreza

Copy link
Copy Markdown
Contributor Author

CI failed on the new total test. Looking into it. Please give me a few minutes!

@shahwazreza

Copy link
Copy Markdown
Contributor Author

Hey, @mbutrovich. CI fails on the new total test. CI runs the tests with the backtrace feature on, so the error string gets a backtrace appended after the message, and the exact assert_eq! doesn't match (the message itself is right). What's the preferred way to approach this?

@mbutrovich mbutrovich left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @shahwazreza for folding in the changes.

@mbutrovich

Copy link
Copy Markdown
Contributor

What's the preferred way to approach this?

Sorry, that one came from my suggestion. DataFusionError::strip_backtrace() returns the message without the backtrace, and other function tests compare errors that way, for example in date_bin.rs. I left a suggestion on the line.

@mbutrovich mbutrovich left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved pending CI.

@shahwazreza

Copy link
Copy Markdown
Contributor Author

Thank you very much for you help!

@mbutrovich
mbutrovich added this pull request to the merge queue Nov 5, 2026
Merged via the queue into apache:main with commit 9bc5faa Nov 5, 2026
44 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

functions Changes to functions implementation v57.0.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

repeat on LargeUtf8 aborts the process on a result size no allocation can satisfy

2 participants