Skip to content

[format] Report unresolvable JSON string casts instead of a bare NPE - #9588

Merged
JingsongLi merged 2 commits into
apache:masterfrom
LuciferYang:fix/json-cast-null-guard
Sep 4, 2026
Merged

[format] Report unresolvable JSON string casts instead of a bare NPE#9588
JingsongLi merged 2 commits into
apache:masterfrom
LuciferYang:fix/json-cast-null-guard

Conversation

@LuciferYang

Copy link
Copy Markdown
Contributor

Purpose

close #9587

JsonFileReader.convertPrimitiveStringToType's default branch dereferenced the result of CastExecutors.resolve, whose javadoc says it returns null when no rule can be resolved. For a column whose type has no cast from STRING, MULTISET, VARIANT or BLOB, the read failed with a NullPointerException carrying no message. This throws instead, naming the type.

The exception and its wording are the ones the same format already uses at create time, UnsupportedOperationException("Unsupported data type for JSON format: X") from JsonFileFormat.validateDataType, so both stages report the same thing. The other STRING-to-X resolve sites already do something sensible: CsvParser falls back to the raw string, and DefaultValueUtils and the StringToArray/Map/Row rules throw.

Reaching it needs a format table. SchemaValidation is the only entry point for validateDataFields, so a managed table rejects these types at create time, while a format table is created through CatalogUtils.validateCreateTable, which does not call it.

One limit worth stating plainly: with json.ignore-parse-errors = true, handleParseError swallows this like any other conversion failure, so the row is emitted with that column null. This improves the default configuration. Making that path fail loudly means resolving the casts once when the reader is built, which is a change of its own.

Tests

JsonFileFormatTest.testUnresolvableCastFailsWithClearMessage reads a one-line JSON file with a MULTISET<STRING> read type and asserts both the root cause type and its message. Asserting the type matters here, since the message alone would also pass if the thrown type changed, and the type is the point of the change.

Against the unfixed reader the root cause is a NullPointerException with no message, so the assertion fails on the type.

mvn -pl paimon-format test on JDK 8: 597 tests, 0 failures. spotless:check and checkstyle:check are clean.

Adjacent and not included: the same unguarded CastExecutors.resolve dereference exists in ArrayToStringCastRule, MapToStringCastRule, RowToStringCastRule and InternalRowPartitionComputer. I checked that they are unguarded, not that they are reachable, so they seem better handled separately.

convertPrimitiveStringToType's default branch dereferenced the result of
CastExecutors.resolve, whose javadoc says it returns null when no rule can
be resolved. For a column whose type has no cast from STRING, MULTISET,
VARIANT or BLOB, the read failed with a NullPointerException carrying no
message. Throw instead, with the type named.

The exception and its wording match what the same format already says at
create time, UnsupportedOperationException "Unsupported data type for JSON
format: X" from JsonFileFormat.validateDataType, so both stages report the
same thing. The other STRING-to-X resolve sites already do something
sensible: CsvParser falls back to the raw string, and DefaultValueUtils and
the StringToArray/Map/Row rules throw.

Reaching it needs a format table. SchemaValidation is the only entry point
for validateDataFields, so a managed table rejects these types at create
time, while a format table is created through
CatalogUtils.validateCreateTable, which does not call it.

One limit worth stating: with json.ignore-parse-errors = true,
handleParseError still swallows this like any other conversion failure, so
the row is emitted with that column null. The improvement is to the default
configuration. Making that path fail loudly means resolving the casts once
when the reader is built, which is a change of its own.

Assisted-by: GLM-5.3
@JingsongLi

Copy link
Copy Markdown
Contributor

+1

@JingsongLi
JingsongLi merged commit 09e7a7a into apache:master Sep 4, 2026
11 of 13 checks passed
@LuciferYang

Copy link
Copy Markdown
Contributor Author

Thank you @JingsongLi

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Reading a JSON column with no string cast fails with a message-less NullPointerException

2 participants