Repository navigation
Description
Describe the bug
TRY_CAST rejects some struct-to-struct casts at planning time even though CAST accepts them.
CAST validates struct casts by field name, allowing missing nullable fields in the target struct to be filled with NULL. In contrast, TRY_CAST uses Arrow's can_cast_types, which requires the source and target structs to have the same number of fields.
The runtime TryCastExpr already handles struct casts by field name. The inconsistency is therefore in the planning-time validation, which is stricter than necessary.
For example, casting STRUCT<x BIGINT> to STRUCT<x BIGINT, y VARCHAR> succeeds with CAST but fails during planning with TRY_CAST.
To Reproduce
Reproduced with DataFusion 55.2.0.
CAST succeeds:
SELECT cast(named_struct('x', 1) AS STRUCT<x BIGINT, y VARCHAR>) AS s;Result:
{x: 1, y: }
TRY_CAST fails during planning:
SELECT try_cast(named_struct('x', 1) AS STRUCT<x BIGINT, y VARCHAR>) AS s;Error:
This feature is not implemented: Unsupported TRY_CAST from Struct("x": Int64) to Struct("x": Int64, "y": Utf8View)
Expected behavior
TRY_CAST should accept this struct cast and return the same result as CAST:
{x: 1, y: }
More generally, TRY_CAST should accept at planning time every struct cast supported by CAST, while preserving its existing null-on-failure semantics.
Additional context
This issue was encountered in [delta-rs](delta-io/delta-rs#4889 (comment)), where a merge with schema evolution and safe_cast enabled failed because of this behavior.
As a workaround, [delta-rs PR #4917](delta-io/delta-rs#4917) uses CAST instead of TRY_CAST for widened fields.
Ion Koutsouris also noted that the same issue occurs in DataFusion 55.1.
Willingness to contribute
I plan to contribute a fix for this bug independently
Activity
ahlag commentedon Oct 20, 2026
take
fix(core): allow safe_cast when merge widens a struct (#4917)
fix(core): allow safe_cast when merge widens a struct (delta-io#4917)
fix(core): allow safe_cast when merge widens a struct (delta-io#4917)
fix(core): allow safe_cast when merge widens a struct (#4917)