You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Python][C++] 25.0.0 aarch64 wheel: deterministic dictionary-decode failure on Neoverse V1 / AWS Graviton3 (SIGSEGV via iter_batches; ArrowInvalid single-threaded); N1/V2 unaffected; 24.0.0 OK #50503
Describe the bug, including details regarding any error messages, version, and platform.
Summary: the pyarrow 25.0.0 manylinux aarch64 wheel deterministically fails to decode dictionary-encoded Parquet on AWS Graviton3 (Neoverse V1, CPU part 0xd40) hosts. The same files, same container image, same code path work correctly on Graviton2 (Neoverse N1, 0xd0c) and Graviton4 (Neoverse V2, 0xd4f), and everything works on all three CPU generations with pyarrow 24.0.0.
Symptoms on Graviton3 + 25.0.0:
ParquetFile.iter_batches() with default use_threads=True → hard SIGSEGV (faulthandler shows the crash inside native decode).
use_threads=False → no crash, but raises ArrowInvalid: Index not in dictionary bounds — i.e. single-threaded decode is also wrong, so this is not a threading race and use_threads=False is not a mitigation.
Determinism evidence (from an internal investigation; counts are per 8 identical scan tasks on a fixed corpus per arm, tasks landing on random ARM host generations on AWS Fargate):
pyarrow 25.0.0, defaults: 3/8 tasks failed — exactly the tasks placed on 0xd40 hosts.
pyarrow 25.0.0, use_threads=False: 4/8 failed with ArrowInvalid — again exactly the 0xd40 placements.
Same base image with only pyarrow==24.0.0 swapped in: 8/8 green across all host generations.
Within a failing task: re-decoding the exact same bytes twice fails identically; re-downloading the file (sha256-verified identical) fails identically; the same file decoded on N1/V2 hosts or on x86-64 is byte-for-byte correct. 12 probe tasks reading /proc/cpuinfo: failure correlates 100% with CPU part 0xd40.
The failing wheel was installed from PyPI (pyarrow==25.0.0, cp312 manylinux aarch64) in a python:3.12-slim (Debian, glibc 2.41) container.
Files that trigger it: zstd-compressed Parquet written by earlier pyarrow (write_table, defaults → dictionary-encoded string columns), ~500k rows per file, ~27 columns (strings, int64, date32, bool, one timestamp). Unfortunately the data is proprietary financial content and we cannot attach a triggering file. We have not yet managed to isolate a synthetic reproducer (we currently have no pinned-Graviton3 test host — Fargate placement is random), but the failure is 100% deterministic per (file, 0xd40 host, 25.0.0).
Hypothesis: a Neoverse-V1-specific code path in the 25.0.0 aarch64 build — V1 is the only one of the three affected/unaffected cores with 256-bit SVE (N1 has no SVE, V2 is 128-bit SVE2), so an SVE(-width)-dispatched kernel in the dictionary decode path is our leading suspect. Related plumbing: #47769 (dynamic dispatch on ARM64) / xsimd bump #49921.
Repro shape (on a Graviton3 host, e.g. EC2 c7g/m7g/r7g, with any sufficiently large dictionary-encoded zstd Parquet):
importpyarrow.parquetaspqpf=pq.ParquetFile(path)
forbatchinpf.iter_batches(batch_size=5000): # SIGSEGV on 0xd40 with 25.0.0pass# use_threads=False instead → ArrowInvalid: Index not in dictionary bounds
We are happy to run candidate wheels/builds or additional diagnostics (faulthandler tracebacks, ARROW_USER_SIMD_LEVEL sweeps, etc.) on Graviton3 and report back — please tell us what would be most useful.
We had this happen to us on Gravitron 3 Lambda instances. I can share an affected Parquet file here. Symptom in this case were absolutely mysterious duplicate datetime indices when loading in Python.
pyarrow 25.0.0 release (pip installed) crashed with "SIGSEGV on 0xd40".
I built arrow from tip, it didn't crash (maybe due to different build args, not sure). Still debugging.
@cyb70289 where you able to find anything? Building from tip not being able to reproduce is interesting? Did you use the nightly wheels or did you build pyarrow yourself? You can use the latest nightly wheels from:
Additional data points + a public 6-line reproducer (independent hit of what looks like the same bug)
Environment: AWS c7g.large (Graviton3 / Neoverse V1; sve svebf16 svei8mm in cpuinfo), Ubuntu 24.04 aarch64, kernel 6.17.0-1019-aws, CPython 3.13, manylinux aarch64 wheel pyarrow==25.0.0. The same versions on Apple Silicon macOS (NEON-only arm64) are not affected — consistent with the SVE-dispatch suspicion.
1. Public minimal repro — no proprietary data needed. A single dictionary-encoded int64 column with 300 distinct values comes back with silently duplicated values (no crash, no error):
importpyarrowaspa, pyarrow.parquetaspqvals=list(range(100_000, 100_300))
pq.write_table(pa.table({"x": pa.array(vals, pa.int64())}), "/tmp/min.parquet")
back=pq.read_table("/tmp/min.parquet")["x"].to_pylist()
print("match:", back==vals, "| unique:", len(set(back)), "of", len(back))
# Graviton3 + pyarrow 25.0.0: match: False | unique: 84 of 300# same + ARROW_USER_SIMD_LEVEL=NONE: match: True | unique: 300 of 300# same box + pyarrow 24.0.0: match: True | unique: 300 of 300
Unlike the SIGSEGV / "Index not in dictionary bounds" reported above, on our data the flat-column failure mode is silent wrong data (values repeated from earlier in the page), fully deterministic across runs, identical with use_threads=False — so the manifestation seems data-shape-dependent, which makes the silent case the scarier one.
2. ARROW_USER_SIMD_LEVEL=NONE fully fixes every read path on this box (the sweep offered above) — pointing at a runtime-dispatched SIMD kernel.
3. Not codec-related. Re-encoding the same data as zstd, snappy, and uncompressed gives identical corruption; writing with use_dictionary=False avoids it for flat columns → the corrupt path is the RLE/bit-packed dictionary-index decode.
4. Repetition/definition levels are also affected (same RLE/bit-packed decoder): reading tables that contain a list<struct<decimal128, decimal128>> column on this box raises e.g. OSError: Malformed levels. min: 0 max: 21827 out of range. Max Level: 1 or ArrowInvalid: Column 7 named asks expected length 218 but got length 239 (the message varies between layouts), even for files written with use_dictionary=False. So the blast radius is wider than dictionary decode.
5. Write path appears unaffected: parquet written by 25.0.0 on the same box is read back correctly by polars 1.42.1 and by pyarrow 24.0.0 (update-id chains over millions of rows verify clean).
Happy to run candidate wheels or further env sweeps on this box.
@cyb70289 where you able to find anything? Building from tip not being able to reproduce is interesting? Did you use the nightly wheels or did you build pyarrow yourself? You can use the latest nightly wheels from:
Nightly build also failed. @raulcd , do you know how to build the release binaries? My manual build probably have different build options, cannot reproduce the issue. Needs binary with debug info.
I could not reproduce, even with the pip installed pyarrow 25.0.0 on with m7gd.xlarge (Graviton 3 / Neoverse V1: 6.12.94+deb13-cloud-arm64, glibc 2.41). I do find this surprising, I wonder if I messed up something.
This is strange. I can reproduce in on a m7gd.xlarge instance, pyarrow 25.0.0, ubuntu-24.04, 6.17.0-1017-aws, also on debian-13 with 6.12.94+deb13-cloud-arm64 kernel.
This is strange. I can reproduce in on a m7gd.xlarge instance, pyarrow 25.0.0, ubuntu-24.04, 6.17.0-1017-aws, also on debian-13 with 6.12.94+deb13-cloud-arm64 kernel.
Ha because I think I was focused on reproducing the segfaults, so I may have read the print statement too fast.
Surprisingly, ARROW_USER_SIMD_LEVEL=SVE128 passes the test.
I guess because there is no fallback SVE256 to SVE128 (on purpose) so this setting will actually run Neon.
Just thinking about next steps, once we have a proper, reproducible fix. This probably deserves a patch release and yanking the wheels for 25.0.0 on PyPI, @pitrou what are your thoughts on it?
Activity
conzy commentedon Jul 14, 2026
Also experiencing this on Fargate
DEBUG: disable regular CI, add Graviton3 SVE-256 repro workflow
vfilter commentedon Jul 16, 2026
We had this happen to us on Gravitron 3 Lambda instances. I can share an affected Parquet file here. Symptom in this case were absolutely mysterious duplicate datetime indices when loading in Python.
d72579f558c154379de39b75272dc612588fda4b.parquet.zip
cyb70289 commentedon Jul 17, 2026
Reproduced this issue on Graviton 3, with a parquet file generated by LLM based on @eaglenebulaplayer 's description.
gen-test-parquet.py
pyarrow 25.0.0 release (pip installed) crashed with "SIGSEGV on 0xd40".
I built arrow from tip, it didn't crash (maybe due to different build args, not sure). Still debugging.
raulcd commentedon Jul 20, 2026
@cyb70289 where you able to find anything? Building from tip not being able to reproduce is interesting? Did you use the nightly wheels or did you build pyarrow yourself? You can use the latest nightly wheels from:
Klavinco commentedon Jul 20, 2026
Additional data points + a public 6-line reproducer (independent hit of what looks like the same bug)
Environment: AWS c7g.large (Graviton3 / Neoverse V1;
sve svebf16 svei8mmin cpuinfo), Ubuntu 24.04 aarch64, kernel 6.17.0-1019-aws, CPython 3.13, manylinux aarch64 wheelpyarrow==25.0.0. The same versions on Apple Silicon macOS (NEON-only arm64) are not affected — consistent with the SVE-dispatch suspicion.1. Public minimal repro — no proprietary data needed. A single dictionary-encoded int64 column with 300 distinct values comes back with silently duplicated values (no crash, no error):
Unlike the SIGSEGV / "Index not in dictionary bounds" reported above, on our data the flat-column failure mode is silent wrong data (values repeated from earlier in the page), fully deterministic across runs, identical with
use_threads=False— so the manifestation seems data-shape-dependent, which makes the silent case the scarier one.2.
ARROW_USER_SIMD_LEVEL=NONEfully fixes every read path on this box (the sweep offered above) — pointing at a runtime-dispatched SIMD kernel.3. Not codec-related. Re-encoding the same data as zstd, snappy, and uncompressed gives identical corruption; writing with
use_dictionary=Falseavoids it for flat columns → the corrupt path is the RLE/bit-packed dictionary-index decode.4. Repetition/definition levels are also affected (same RLE/bit-packed decoder): reading tables that contain a
list<struct<decimal128, decimal128>>column on this box raises e.g.OSError: Malformed levels. min: 0 max: 21827 out of range. Max Level: 1orArrowInvalid: Column 7 named asks expected length 218 but got length 239(the message varies between layouts), even for files written withuse_dictionary=False. So the blast radius is wider than dictionary decode.5. Write path appears unaffected: parquet written by 25.0.0 on the same box is read back correctly by polars 1.42.1 and by pyarrow 24.0.0 (update-id chains over millions of rows verify clean).
Happy to run candidate wheels or further env sweeps on this box.
cyb70289 commentedon Jul 21, 2026
Nightly build also failed. @raulcd , do you know how to build the release binaries? My manual build probably have different build options, cannot reproduce the issue. Needs binary with debug info.
cyb70289 commentedon Jul 21, 2026
@AntoinePrv , do you think there might be some edge cases of SIMD dispatcher that might break on SVE-256 machine?
raulcd commentedon Jul 21, 2026
Yes, currently the release binaries are built using archery (docker). From this latest nightly workflow the command to reproduce wheels for 3.14:
This Dockerfile is the one that gets run which manages third party dependencies via vcpkg:
https://github.com/apache/arrow/blob/0f54c056e6d3576344971121708fc93deeaa3918/ci/docker/python-wheel-manylinux.dockerfile
And the build script for the wheel itself is here:
https://github.com/apache/arrow/blob/0f54c056e6d3576344971121708fc93deeaa3918/ci/scripts/python_wheel_xlinux_build.sh
AntoinePrv commentedon Jul 21, 2026
Gonna investigate!
AntoinePrv commentedon Jul 21, 2026
I could not reproduce, even with the pip installed pyarrow 25.0.0 on with
m7gd.xlarge(Graviton 3 / Neoverse V1: 6.12.94+deb13-cloud-arm64, glibc 2.41). I do find this surprising, I wonder if I messed up something.cyb70289 commentedon Jul 22, 2026
This is strange. I can reproduce in on a
m7gd.xlargeinstance, pyarrow 25.0.0, ubuntu-24.04, 6.17.0-1017-aws, also on debian-13 with 6.12.94+deb13-cloud-arm64 kernel.Using @Klavinco 's test code:
Surprisingly,
ARROW_USER_SIMD_LEVEL=SVE128passes the test.AntoinePrv commentedon Jul 22, 2026
Ha because I think I was focused on reproducing the segfaults, so I may have read the
printstatement too fast.I guess because there is no fallback SVE256 to SVE128 (on purpose) so this setting will actually run Neon.
5 remaining items
AntoinePrv commentedon Jul 23, 2026
I think you may need LTO enabled to reproduce.
In addition, would some of you mind double checking this wheel solves the issue? @cyb70289 @Klavinco @eaglenebulaplayer
https://github.com/ursacomputing/crossbow/actions/runs/29994419195/artifacts/8558628657
cyb70289 commentedon Jul 23, 2026
Great! This wheel runs correctly per my test on graviton3. Both the segfault and wrong value cases pass.
raulcd commentedon Jul 23, 2026
Just thinking about next steps, once we have a proper, reproducible fix. This probably deserves a patch release and yanking the wheels for 25.0.0 on PyPI, @pitrou what are your thoughts on it?
pitrou commentedon Jul 23, 2026
Hmm, perhaps. Still, would be nice to print the actual values.
cyb70289 commentedon Jul 23, 2026
Wrong
backvaluespitrou commentedon Jul 23, 2026
@cyb70289 Can you try the wheel that was uploaded as an artifact in https://github.com/ursacomputing/crossbow/actions/runs/30025352042 ?
cyb70289 commentedon Jul 24, 2026
It works fine.
pyarrow-26.0.0.dev45GH-50503: [Parquet] Remove SVE128 unpack (#50611)
pitrou commentedon Jul 30, 2026
Issue resolved by pull request 50611
#50611