google/gson · error · JsonIOException

${memberDescription} is not accessible and ReflectionAccessF

Error message

${memberDescription} is not accessible and ReflectionAccessFilter does not permit making it accessible. Register a TypeAdapter for the declaring type, adjust the access filter or increase the visibility of the element and its declaring type.

What it means

When a ReflectionAccessFilter returns BLOCK_INACCESSIBLE, Gson will not call setAccessible(true) on fields/constructors. checkAccessible() then verifies the member is accessible under normal Java access rules; if it is not (e.g. a private field in a non-exported package, or an inaccessible record constructor), it throws JsonIOException. This respects Java module encapsulation (JPMS) and access boundaries rather than forcing accessibility.

Source

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

      @SuppressWarnings("unchecked")
      TypeAdapter<T> adapter =
          (TypeAdapter<T>)
              new RecordAdapter<>(
                  raw, getBoundFields(gson, type, raw, blockInaccessible, true), blockInaccessible);
      return adapter;
    }

    ObjectConstructor<T> constructor = constructorConstructor.get(type, true);
    return new FieldReflectionAdapter<>(
        constructor, getBoundFields(gson, type, raw, blockInaccessible, false));
  }

  private static <M extends AccessibleObject & Member> void checkAccessible(
      Object object, M member) {
    if (!ReflectionAccessFilterHelper.canAccess(
        member, Modifier.isStatic(member.getModifiers()) ? null : object)) {
      String memberDescription = ReflectionHelper.getAccessibleObjectDescription(member, true);
      throw new JsonIOException(
          memberDescription
              + " is not accessible and ReflectionAccessFilter does not permit making it"
              + " accessible. Register a TypeAdapter for the declaring type, adjust the access"
              + " filter or increase the visibility of the element and its declaring type.");
    }
  }

  private BoundField createBoundField(
      Gson context,
      Field field,
      Method accessor,
      String serializedName,
      TypeToken<?> fieldType,
      boolean serialize,
      boolean blockInaccessible) {

    boolean isPrimitive = Primitives.isPrimitive(fieldType.getRawType());

View on GitHub (pinned to 310ac341f2)

Solutions

  1. Register a custom TypeAdapter for the declaring type so reflection on its fields is unnecessary
  2. Change the ReflectionAccessFilter to ALLOW for that type (if acceptable under your security model)
  3. Increase visibility of the element and its declaring type (make the field/package-accessible, or add 'opens' in module-info for JPMS)
  4. Annotate the field with @JsonAdapter to supply a non-reflective adapter

Example fix

// before - private field inaccessible under BLOCK_INACCESSIBLE
class Box { private int secret; }
gson.fromJson(json, Box.class); // throws

// after option 1 - widen visibility
class Box { int secret; }

// after option 2 - register a TypeAdapter
Gson gson = new GsonBuilder()
    .registerTypeAdapter(Box.class, new BoxAdapter())
    .create();
Defensive patterns

Strategy: type-guard

Validate before calling

// Pre-check field accessibility before relying on reflective (de)serialization
Field f = MyType.class.getDeclaredField("secret");
boolean accessible = Modifier.isPublic(f.getModifiers())
    || (f.canAccess(instance));
if (!accessible) {
    throw new IllegalStateException("Field not accessible under BLOCK_INACCESSIBLE: " + f);
}

Type guard

// Confirm a member is accessible under current access rules
static boolean isAccessible(Field f, Object instance) {
    try {
        return f.canAccess(instance);
    } catch (Exception e) {
        return false;
    }
}

Try / catch

try {
  MyType obj = gson.fromJson(json, MyType.class);
} catch (com.google.gson.JsonIOException e) {
  // '... is not accessible...': widen visibility, open the package (JPMS), or register a TypeAdapter
}

Prevention

When it happens

Trigger: Deserializing a type with private/inaccessible fields under a BLOCK_INACCESSIBLE filter; serializing records whose accessor/constructor is not accessible; JPMS strong encapsulation (Java 16+ default) denying access to a package.

Common situations: Java 16+ with strong encapsulation; modules that do not 'opens' their packages to Gson; library types with restrictive visibility; switching a filter from ALLOW to BLOCK_INACCESSIBLE.

Related errors


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