google/gson · error · JsonIOException

ReflectionAccessFilter does not permit using reflection for

Error message

ReflectionAccessFilter does not permit using reflection for " + raw + ". Register a TypeAdapter for this type or adjust the access filter.

What it means

Thrown by ReflectiveTypeAdapterFactory.create() as a JsonIOException when a registered ReflectionAccessFilter returns FilterResult.BLOCK_ALL for the type being adapted. Gson refuses to use reflection (field access) for that class and requires either an explicit TypeAdapter or an adjustment to the filter. This is a security-hardening mechanism to prevent reflection on sensitive types.

Source

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

          return null;
        }

        @Override
        public void write(JsonWriter out, T value) throws IOException {
          out.nullValue();
        }

        @Override
        public String toString() {
          return "AnonymousOrNonStaticLocalClassAdapter";
        }
      };
    }

    FilterResult filterResult =
        ReflectionAccessFilterHelper.getFilterResult(reflectionFilters, raw);
    if (filterResult == FilterResult.BLOCK_ALL) {
      throw new JsonIOException(
          "ReflectionAccessFilter does not permit using reflection for "
              + raw
              + ". Register a TypeAdapter for this type or adjust the access filter.");
    }
    boolean blockInaccessible = filterResult == FilterResult.BLOCK_INACCESSIBLE;

    // If the type is actually a Java Record, we need to use the RecordAdapter instead. This will
    // always be false on JVMs that do not support records.
    if (ReflectionHelper.isRecord(raw)) {
      @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);

View on GitHub (pinned to 8b8628c656)

Solutions

  1. Register a custom TypeAdapter (or JsonSerializer/JsonDeserializer) for the blocked type via GsonBuilder.registerTypeAdapter(...).
  2. Adjust the ReflectionAccessFilter to return ALLOW for this type, or BLOCK_INACCESSIBLE instead of BLOCK_ALL if partial reflection is acceptable.
  3. Annotate the type with @JsonAdapter(SomeAdapter.class) so Gson uses your adapter without reflection.
  4. Narrow the filter's scope so it only blocks the intended sensitive types.

Example fix

// before: filter blocks java.util.Currency, no adapter registered
Gson gson = new GsonBuilder()
  .addReflectionAccessFilter((c, t) -> t.getName().startsWith("java.") ? FilterResult.BLOCK_ALL : FilterResult.ALLOW)
  .create();
gson.toJson(myCurrency); // throws JsonIOException

// after: register an adapter for the blocked type
Gson gson = new GsonBuilder()
  .addReflectionAccessFilter((c, t) -> t.getName().startsWith("java.") ? FilterResult.BLOCK_ALL : FilterResult.ALLOW)
  .registerTypeAdapter(Currency.class, new CurrencyAdapter())
  .create();
gson.toJson(myCurrency);
Defensive patterns

Strategy: fallback

Validate before calling

// Provide a TypeAdapter for any type you block via ReflectionAccessFilter
Gson gson = new GsonBuilder()
  .addReflectionAccessFilter((c, t) -> isBlocked(t) ? FilterResult.BLOCK_ALL : FilterResult.ALLOW)
  .registerTypeAdapter(MyBlockedType.class, new MyBlockedTypeAdapter())
  .create();

Try / catch

try {
  return gson.toJson(obj);
} catch (JsonIOException e) {
  if (e.getMessage() != null && e.getMessage().contains("ReflectionAccessFilter does not permit")) {
    // build a fresh Gson without the blocking filter, or with an adapter for the type
    Gson fallback = buildGsonWithAdapterFor(obj.getClass());
    return fallback.toJson(obj);
  }
  throw e;
}

Prevention

When it happens

Trigger: Registering a ReflectionAccessFilter via GsonBuilder.addReflectionAccessFilter(...) that blocks a type, then attempting to serialize/deserialize that type (or a type whose fields reference it) without a custom TypeAdapter. The filter's filterCheck returns BLOCK_ALL and Gson has no other adapter to fall back to.

Common situations: Security reviews that add filters blocking platform or internal classes; blocking third-party library types that the model transitively references; overly-broad filters (e.g. blocking all java.* or a package) catching application types; upgrading Gson and adopting the reflection filter feature without providing adapters for blocked types.

Related errors


AI-assisted analysis of google/gson@8b8628c656 (2026-08-04). Data as JSON: /data/errors/2b82a67a0563804f.json. Report an issue: GitHub.