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
AtomicIntegerArray deserializer crashes on JSON null (IllegalStateException) — symmetric fix to #3038 #3047
When the JsonReader is positioned at a NULL token, nextInt() throws IllegalStateException — which is not caught here, so it propagates raw instead of being converted to a JsonSyntaxException.
PR #3038 (merged 2026-06-22) fixed the symmetric issue in AtomicLongArray. That adapter delegates to longAdapter.read(in), which returns null for a JSON null; the fix added an explicit null-check:
Numbervalue = longAdapter.read(in);
if (value == null) {
thrownewJsonSyntaxException("null is not a valid AtomicLongArray element");
}
list.add(value.longValue());
AtomicIntegerArray was not updated with the same treatment.
Expected behaviour
A JSON null element inside an AtomicIntegerArray should throw a JsonSyntaxException (same as AtomicLongArray after #3038), not a raw IllegalStateException.
Suggested fix
Mirror the approach used in the AtomicLongArray adapter — either:
Option A — peek before reading:
while (in.hasNext()) {
try {
if (in.peek() == com.google.gson.stream.JsonToken.NULL) {
thrownewJsonSyntaxException("null is not a valid AtomicIntegerArray element");
}
intinteger = in.nextInt();
list.add(integer);
} catch (NumberFormatExceptione) {
thrownewJsonSyntaxException(e);
}
}
Option B — delegate to INTEGER type adapter (returns null for JSON null, already handles this safely) and add a null-check, consistent with the AtomicLongArray pattern.
A regression test analogous to the one added in #3038 for AtomicLongArray should also be added.
Are you sure that the IllegalStateException propagates as is to the caller? In my testing it looks like it is wrapped in a JsonSyntaxException as desired, here:
Your suggested fix checking for JSON null would probably not suffice; the IllegalStateException would also occur for other unexpected JSON value types, e.g. for [1,true,3].
Is the exception message you pasted even real (or artificially crafted)? JsonReader's error reporting is not exact in all situations, for example for literals such as null it already advances the column, so for me the actual error message is "... at line 1 column 8 path $[1]" (note the 8 instead of the 4).
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected an int but was NULL at line 1 column 8 path $[1]
Not a raw, uncaught IllegalStateException — Gson.fromJson(JsonReader, TypeToken) already catches IllegalStateException and wraps it as JsonSyntaxException (Gson.java around line 1123), same as you found. So the crash as described in this issue doesn't reproduce via the standard fromJson API on the current code.
The one real (minor) difference from the AtomicLongArray fix in #3038 is the exception message/path: today it's the generic "Expected an int but was NULL at line 1 column 8 path $[1]" rather than something AtomicIntegerArray-specific like "null is not a valid AtomicIntegerArray element", and as you noted, the same applies to any other unexpected token type (e.g. [1,true,3]), not just null. That's a much smaller, cosmetic-message improvement rather than a crash fix though, so probably not worth a PR on its own — wanted to close the loop on the reproduction question first.
@Marcono1234@amitmishra11 — you are both right, and I owe an overdue correction. I have now actually run it.
gson 2.14.0 (current release), JDK 21
AtomicIntegerArray [1,null,3] -> com.google.gson.JsonSyntaxException
java.lang.IllegalStateException: Expected an int but was NULL at line 1 column 8 path $[1]
AtomicIntegerArray [1,true,3] -> com.google.gson.JsonSyntaxException
java.lang.IllegalStateException: Expected an int but was BOOLEAN at line 1 column 8 path $[1]
AtomicIntegerArray [1,2,3] -> NO EXCEPTION (control)
So: no raw IllegalStateException reaches the caller.Gson.fromJson wraps it, exactly where @Marcono1234 pointed. The premise of this issue is wrong, and the [1,true,3] note is right too — this is about unexpected token types generally, not about null.
On the exception message: it was not real, and that is the part I should own. I reconstructed it from reading the adapter rather than running it, which is why the column said 4 and the actual value is 8. Presenting a derived string in the shape of observed output is a worse error than the wrong conclusion it supported, because it is the thing that made the report look verified. Thank you for asking directly instead of letting it stand.
One thing that did fall out of running it
The same probe against AtomicLongArray on the released jars:
gson 2.13.1 and 2.14.0
AtomicLongArray [1,null,3] -> java.lang.NullPointerException
Cannot invoke "java.lang.Number.longValue()" because the return value of
"com.google.gson.TypeAdapter.read(com.google.gson.stream.JsonReader)" is null
AtomicLongArray [1,true,3] -> com.google.gson.JsonSyntaxException
java.lang.IllegalStateException: Expected a long but was BOOLEAN at line 1 column 8 path $[1]
An unwrapped NullPointerException out of fromJson, on null only. fromJson catches IllegalStateException and NumberFormatException, so the NPE from value.longValue() on a null return goes straight through.
This is already fixed on main by #3038, and I confirmed that rather than assuming it:
main, TypeAdapters.java:387
"null is not a valid AtomicLongArray element; at path " + in.getPreviousPath()
So it is a release-timing observation, not a new bug: the guard exists in the repository and not in any jar on Maven Central yet. Worth knowing only if someone triages an NPE report from a user on 2.14.0 and cannot find the cause in main.
Where that leaves this issue
The asymmetry I originally described does exist on main, but it is the one @amitmishra11 characterised: AtomicLongArray refuses a JSON null with a specific message, AtomicIntegerArray reports the generic wrapped IllegalStateException. Both are JsonSyntaxException, neither crashes, and the difference is message quality on a path that also covers booleans, strings and objects.
I agree that is not worth a PR on its own and I am not going to argue for one. Happy for this to be closed as invalid — the bug as filed does not exist. If you would rather keep it open as a small consistency note for AtomicIntegerArray, I am glad to write that patch, but only if you want it; the call is yours.
Sorry for the noise, and for leaving this sitting after you had both already done the work of disproving it.
Happy for this to be closed as invalid — the bug as filed does not exist.
I am not a maintainer of the project, but I think given that this issue and all the comments are currently about this non-existent bug I don't think it is useful to keep it open or to repurpose it.
If you want, feel free to wait for a response from the maintainers though.
This report describes a non-existent issue (see last two comments above), and for some reason this attracts (LLM-generated / -assisted?) PRs, which then also claim to fix this non-existent issue.
Maybe some of these PRs are still useful due to exception improvements, but none of them fix an actual "bug" I think, at least not this (non-existent) one here.
Activity
Marcono1234 commentedon Jun 26, 2026
Are you sure that the
IllegalStateExceptionpropagates as is to the caller? In my testing it looks like it is wrapped in aJsonSyntaxExceptionas desired, here:gson/gson/src/main/java/com/google/gson/Gson.java
Lines 1123 to 1124 in c9f3fd5
Side notes:
IllegalStateExceptionwould also occur for other unexpected JSON value types, e.g. for[1,true,3].JsonReader's error reporting is not exact in all situations, for example for literals such asnullit already advances the column, so for me the actual error message is "... at line 1 column 8 path $[1]" (note the 8 instead of the 4).amitmishra11 commentedon Jun 28, 2026
Confirmed @Marcono1234's suspicion above: I tested this directly against the current
mainbranch (unmodified):This throws:
Not a raw, uncaught
IllegalStateException—Gson.fromJson(JsonReader, TypeToken)already catchesIllegalStateExceptionand wraps it asJsonSyntaxException(Gson.java around line 1123), same as you found. So the crash as described in this issue doesn't reproduce via the standardfromJsonAPI on the current code.The one real (minor) difference from the
AtomicLongArrayfix in #3038 is the exception message/path: today it's the generic "Expected an int but was NULL at line 1 column 8 path $[1]" rather than something AtomicIntegerArray-specific like "null is not a valid AtomicIntegerArray element", and as you noted, the same applies to any other unexpected token type (e.g.[1,true,3]), not justnull. That's a much smaller, cosmetic-message improvement rather than a crash fix though, so probably not worth a PR on its own — wanted to close the loop on the reproduction question first.Throw JsonSyntaxException instead of raw exceptions in built-in adapters
mahirhir commentedon Sep 12, 2026
@Marcono1234 @amitmishra11 — you are both right, and I owe an overdue correction. I have now actually run it.
So: no raw
IllegalStateExceptionreaches the caller.Gson.fromJsonwraps it, exactly where @Marcono1234 pointed. The premise of this issue is wrong, and the[1,true,3]note is right too — this is about unexpected token types generally, not aboutnull.On the exception message: it was not real, and that is the part I should own. I reconstructed it from reading the adapter rather than running it, which is why the column said 4 and the actual value is 8. Presenting a derived string in the shape of observed output is a worse error than the wrong conclusion it supported, because it is the thing that made the report look verified. Thank you for asking directly instead of letting it stand.
One thing that did fall out of running it
The same probe against
AtomicLongArrayon the released jars:An unwrapped
NullPointerExceptionout offromJson, onnullonly.fromJsoncatchesIllegalStateExceptionandNumberFormatException, so the NPE fromvalue.longValue()on a null return goes straight through.This is already fixed on
mainby #3038, and I confirmed that rather than assuming it:So it is a release-timing observation, not a new bug: the guard exists in the repository and not in any jar on Maven Central yet. Worth knowing only if someone triages an NPE report from a user on 2.14.0 and cannot find the cause in
main.Where that leaves this issue
The asymmetry I originally described does exist on
main, but it is the one @amitmishra11 characterised:AtomicLongArrayrefuses a JSON null with a specific message,AtomicIntegerArrayreports the generic wrappedIllegalStateException. Both areJsonSyntaxException, neither crashes, and the difference is message quality on a path that also covers booleans, strings and objects.I agree that is not worth a PR on its own and I am not going to argue for one. Happy for this to be closed as invalid — the bug as filed does not exist. If you would rather keep it open as a small consistency note for
AtomicIntegerArray, I am glad to write that patch, but only if you want it; the call is yours.Sorry for the noise, and for leaving this sitting after you had both already done the work of disproving it.
Marcono1234 commentedon Sep 14, 2026
Thanks for following up on this!
I am not a maintainer of the project, but I think given that this issue and all the comments are currently about this non-existent bug I don't think it is useful to keep it open or to repurpose it.
If you want, feel free to wait for a response from the maintainers though.
Marcono1234 commentedon Sep 22, 2026
@eamonnmcmanus, can you please close this issue?
This report describes a non-existent issue (see last two comments above), and for some reason this attracts (LLM-generated / -assisted?) PRs, which then also claim to fix this non-existent issue.
Maybe some of these PRs are still useful due to exception improvements, but none of them fix an actual "bug" I think, at least not this (non-existent) one here.