Uh oh!
There was an error while loading. Please reload this page.
GH-39914: [pyarrow] Fall back to schema field type for unparseable complex dtype metadata - #51167
Open
tritsystem wants to merge 1 commit into
Open
GH-39914: [pyarrow] Fall back to schema field type for unparseable complex dtype metadata#51167tritsystem wants to merge 1 commit into
tritsystem wants to merge 1 commit into
Conversation
…le complex dtype metadata pd.read_parquet() (and Table.to_pandas() generally) raises TypeError when a column's pandas metadata records a complex ArrowDtype (list, struct, dictionary, ...) as its 'numpy_type', e.g. "list<item: string>[pyarrow]". _get_extension_dtypes() passes this string straight to pandas.api.types.pandas_dtype(), which cannot parse nested Arrow type syntax and raises TypeError -- so any DataFrame that has such a column can never round-trip through parquet with the default (numpy) backend, and this has stayed broken since 2023. apacheGH-39914 previously fixed the case where an explicit types_mapper / dtype_backend="pyarrow" is passed, by resolving those columns earlier so this code path is skipped entirely. The default backend, and any metadata-only path with no types_mapper, still hit the crash. Fix: when pandas_dtype(dtype) raises TypeError, fall back to building the ArrowDtype directly from the schema's actual field type instead of giving up. The schema always has the precise type available regardless of whether the metadata string can be parsed back. Verified against pandas 3.0.4 + pyarrow 24.0.0: list, struct, and dictionary ArrowDtype columns now round-trip through to_pandas() and parquet with no types_mapper/dtype_backend needed, a double write/read/write/read round-trip of a struct column still works, and plain numpy dtypes plus simple extension dtypes (Int64) are unaffected. Fixespandas-dev/pandas#53011 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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 freeto 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.
Rationale for this change
pd.read_parquet()(andTable.to_pandas()generally, with notypes_mapper/dtype_backend="pyarrow") raisesTypeErrorfor anycolumn whose pandas metadata records a complex
ArrowDtype-- list,struct, or dictionary -- as its
numpy_type, e.g."list<item: string>[pyarrow]". This has been broken since the metadataround-tripping was introduced, and is the long-standing root cause of
pandas-dev/pandas#53011 (open since 2023, still reproducing today with
no workaround at the pandas level).
#39914 (this PR's linked issue) previously fixed the case where an
explicit
types_mapper/dtype_backend="pyarrow"is passed at readtime -- #44720 resolved those columns earlier in
_get_extension_dtypes,so the buggy string-parsing branch is skipped entirely for that path.
The default backend, and any metadata-only path with no
types_mapper, still hit the original crash -- which is why the pandasissue has stayed open and users keep re-discovering it (see the thread's
comments through 2025-08).
What changes are included in this PR?
In
_get_extension_dtypes(), whenpandas_dtype(dtype)raisesTypeErroron the metadata'snumpy_typestring, fall back to buildingthe
ArrowDtypedirectly from the schema's actual field type(
table.schema.field(name).type) instead of propagating the error. Theschema always carries the precise type regardless of whether the
metadata string happens to be parseable, and this is exactly the pattern
several commenters on the pandas issue independently proposed (e.g.
this comment)
but that was never implemented in a merged fix.
Are these changes tested?
Added
test_to_pandas_extension_dtypes_mapping_complex_type_no_types_mapper,covering both a list and a struct
ArrowDtypecolumn round-trippedthrough
Table.to_pandas()with notypes_mapper-- the exact casethat previously crashed. Confirmed red on unpatched code / green after
the fix.
Also manually verified (not just the new test) against pandas 3.0.4 +
pyarrow 24.0.0:
ArrowDtypecolumns round-trip throughboth the default backend and
dtype_backend="pyarrow".scenario from this comment)
still works.
Int64) areunaffected -- no regression to the already-working paths.
Are there any user-facing changes?
This PR contains a "Critical Fix".
This makes
pd.read_parquet(...)(default backend, nodtype_backend="pyarrow"needed) work for any DataFrame containing acomplex
ArrowDtypecolumn (list/struct/dictionary), which currentlyraises an opaque
TypeErrorand has no workaround short of stripping thepandas metadata before writing.
AI Generation Disclosure
Generated with Claude Code. The bug
was found by searching for confirmed, still-open, high-severity issues
across large open-source projects; root-caused and fixed by tracing the
actual
pandas_compat.pysource against the linked pandas issue and theprior partial fix (#44720), then verified against a fresh install of the
latest pandas/pyarrow rather than assumed from the issue thread alone.
🤖 Generated with Claude Code