google/gson · error · JsonParseException

null is not allowed as value for record component

Error message

null is not allowed as value for record component '${fieldName}' of primitive type; at path ${path}

What it means

When deserializing JSON into a record with a primitive-typed component (int, long, boolean, etc.), Gson reads each value into a constructor argument array. A JSON null cannot be assigned to a primitive slot, so readIntoArray throws JsonParseException before the constructor is ever called.

Solutions

  1. Change the primitive record component to its boxed wrapper type (Integer, Long, Boolean) so null is accepted
  2. Pre-process the JSON to replace null values with sensible defaults before calling fromJson
  3. Register a custom TypeAdapter that substitutes a default value (e.g. 0) when the JSON value is null

Example fix

// before
record Person(int age) {}
gson.fromJson("{\"age\":null}", Person.class); // throws

// after
record Person(Integer age) {}
gson.fromJson("{\"age\":null}", Person.class); // age is null, no error
Defensive patterns

Strategy: validation

Validate before calling

// Before deserializing, scan the JSON for nulls on primitive record components
public static void checkPrimitiveNulls(JsonElement json, Class<?> recordType) {
    var components = recordType.getRecordComponents();
    var obj = json.getAsJsonObject();
    for (var c : components) {
        if (c.getType().isPrimitive() && obj.has(c.getName())
                && obj.get(c.getName()).isJsonNull()) {
            throw new IllegalStateException(
                "JSON null for primitive record component: " + c.getName());
        }
    }
}

Type guard

// Prefer boxed types for nullable components
record Person(Integer age) {} // Integer accepts null; int does not

Try / catch

try {
    Person p = gson.fromJson(json, Person.class);
} catch (JsonParseException e) {
    if (e.getMessage().contains("null is not allowed")) {
        // default the primitive or use a nullable wrapper
    }
}

Prevention

When it happens

Trigger: Deserializing JSON containing a null literal for a field mapped to a primitive record component, e.g. {"age": null} into record Person(int age).

Common situations: A backend API returns null for a field the client modeled as a primitive int/long/boolean in a record; schema evolution where a previously-non-null field becomes nullable.

Related errors


AI-assisted analysis of google/gson@310ac341f2 (2026-08-10). Data as JSON: /api/errors/40c0745276410d0d. Report an issue: GitHub.

Appendix: source

Thrown at gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java:262

          fieldValue = field.get(source);
        }

        @SuppressWarnings("ReferenceEquality")
        boolean isSameObject = fieldValue == source;
        if (isSameObject) {
          // avoid direct recursion
          return;
        }
        writer.name(serializedName);
        writeTypeAdapter.write(writer, fieldValue);
      }

      @Override
      void readIntoArray(JsonReader reader, int index, Object[] target)
          throws IOException, JsonParseException {
        Object fieldValue = typeAdapter.read(reader);
        if (fieldValue == null && isPrimitive) {
          throw new JsonParseException(
              "null is not allowed as value for record component '"
                  + fieldName
                  + "' of primitive type; at path "
                  + reader.getPath());
        }
        target[index] = fieldValue;
      }

      @Override
      void readIntoField(JsonReader reader, Object target)
          throws IOException, IllegalAccessException {
        Object fieldValue = typeAdapter.read(reader);
        if (fieldValue != null || !isPrimitive) {
          if (blockInaccessible) {
            checkAccessible(target, field);
          } else if (isStaticFinalField) {
            // Reflection does not permit setting value of `static final` field, even after calling
            // `setAccessible`

View on GitHub (pinned to 310ac341f2)