google/gson · error · RuntimeException

Failed to invoke constructor '" + ReflectionHelper.construct

Error message

Failed to invoke constructor '" + ReflectionHelper.constructorToString(constructor) + "' with args " + Arrays.toString(accumulator)

What it means

Thrown by RecordAdapter.finalize when invoking the record's canonical constructor fails with IllegalAccessException or InstantiationException or IllegalArgumentException (wrapped into one catch). The first two should be near-impossible per Gson's own comments; IllegalArgumentException means a registered adapter returned an object of the wrong type for a constructor argument. Wrapped as a RuntimeException carrying the original exception.

Source

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

                + " same names as the fields in the Java class, and that the order of the"
                + " RecordComponents is the same as the order of the canonical constructor"
                + " parameters.");
      }
      field.readIntoArray(in, componentIndex, accumulator);
    }

    @Override
    T finalize(Object[] accumulator) {
      try {
        return constructor.newInstance(accumulator);
      } catch (IllegalAccessException e) {
        throw ReflectionHelper.createExceptionForUnexpectedIllegalAccess(e);
      }
      // Note: InstantiationException should be impossible because record class is not abstract;
      //  IllegalArgumentException should not be possible unless a bad adapter returns objects of
      //  the wrong type
      catch (InstantiationException | IllegalArgumentException e) {
        throw new RuntimeException(
            "Failed to invoke constructor '"
                + ReflectionHelper.constructorToString(constructor)
                + "' with args "
                + Arrays.toString(accumulator),
            e);
      } catch (InvocationTargetException e) {
        // TODO: JsonParseException ?
        throw new RuntimeException(
            "Failed to invoke constructor '"
                + ReflectionHelper.constructorToString(constructor)
                + "' with args "
                + Arrays.toString(accumulator),
            e.getCause());
      }
    }
  }
}

View on GitHub (pinned to 8b8628c656)

Solutions

  1. Inspect the wrapped exception: IllegalArgumentException -> fix the custom adapter for the named component type.
  2. Ensure the canonical constructor parameter types match what your TypeAdapters produce.
  3. Open the package containing the record in module-info so reflective construction is permitted.
  4. Register a full TypeAdapter for the record so Gson never invokes the canonical constructor reflectively.

Example fix

// before: adapter returns wrong type for primitive component
registerTypeAdapter(int.class, new TypeAdapter<Integer>(){
  public Integer read(JsonReader r){ return r.nextString(); } // String for int
});

// after
public Integer read(JsonReader r){ return r.nextInt(); }
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure adapters for record components return assignable types
for (RecordComponent rc : MyRecord.class.getRecordComponents()) {
  TypeAdapter<?> a = gson.getAdapter(TypeToken.get(rc.getType()));
  // read a sample and check class before relying on it
}

Type guard

null

Try / catch

try {
  gson.fromJson(json, MyRecord.class);
} catch (RuntimeException e) {
  if (e.getMessage().startsWith("Failed to invoke constructor") && !(e.getCause() instanceof InvocationTargetException)) {
    // IllegalAccessException / IllegalArgumentException: fix adapter return types
  } else throw e;
}

Prevention

When it happens

Trigger: A custom TypeAdapter registered for a record component returns a value whose type does not match the canonical constructor parameter (e.g., returns a String for an int parameter); a security manager or module layer denies constructor access after the initial makeAccessible; subclassing tools that make the record abstract. Catch site: line 655.

Common situations: Mixing custom adapters for boxed/primitive components incorrectly; JPMS layer changes after adapter construction; security managers rejecting reflection; buggy generic TypeAdapter returning wrong runtime types.

Related errors


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