AtomicIntegerArray deserializer crashes on JSON null (IllegalStateException) — symmetric fix to #3038

Open Beginner friendly
#3,047 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
88/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
java
Domain
backend

Research direction

Start in TypeAdapters.java by comparing the ATOMIC_INTEGER_ARRAY adapter with the AtomicLongArray change from PR #3038. Run the existing AtomicLongArray regression test as a guide, add an analogous test for a null element in AtomicIntegerArray, and confirm it produces JsonSyntaxException rather than IllegalStateException.

Written by the indexing model from the issue text.

Description

Bug

Deserializing a JSON array that contains a null element into an AtomicIntegerArray crashes with an uncaught IllegalStateException:

new Gson().fromJson("[1,null,3]", AtomicIntegerArray.class);
// throws IllegalStateException: Expected an int but was NULL at line 1 column 4 path $[1]

Root cause

In TypeAdapters.java, the ATOMIC_INTEGER_ARRAY adapter's read() method calls in.nextInt() inside a loop that only catches NumberFormatException:

public AtomicIntegerArray read(JsonReader in) throws IOException {
  List<Integer> list = new ArrayList<>();
  in.beginArray();
  while (in.hasNext()) {
    try {
      int integer = in.nextInt();
      list.add(integer);
    } catch (NumberFormatException e) {
      throw new JsonSyntaxException(e);
    }
  }
  in.endArray();
  ...
}

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.

Relationship to #3038

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:

Number value = longAdapter.read(in);
if (value == null) {
  throw new JsonSyntaxException("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) {
      throw new JsonSyntaxException("null is not a valid AtomicIntegerArray element");
    }
    int integer = in.nextInt();
    list.add(integer);
  } catch (NumberFormatException e) {
    throw new JsonSyntaxException(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.

Environment

  • Gson latest main branch (after #3038 merge)
  • Reproducible with any Gson version where AtomicIntegerArray deserialization is supported
Dominant language
Java
Stars
24.2k
Forks
4.5k
Avg merge
6d 4h
Merged PRs (30d)
12

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from google/gson

All issues in google/gson

Similar issues

More Java issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.