google/gson · error · JsonIOException

Interfaces can't be instantiated! Register an InstanceCreato

Error message

Interfaces can't be instantiated! Register an InstanceCreator or a TypeAdapter for this type. Interface name: ${c.getName()}

What it means

Thrown when Gson attempts to deserialize into an interface type and no InstanceCreator or TypeAdapter is registered. Interfaces cannot be instantiated by any mechanism (reflection, Unsafe, special constructors), so Gson throws this via ThrowingObjectConstructor.construct(). The message names the interface.

Source

Thrown at gson/src/main/java/com/google/gson/internal/ConstructorConstructor.java:424

   * ObjectConstructor}, which would then choose another way of creating the object. And it supports
   * types which are only serialized but not deserialized (compared to directly throwing an
   * exception when the {@code ObjectConstructor} is requested), e.g. when the runtime type of an
   * object is inaccessible, but the compile-time type is accessible.
   */
  private static final class ThrowingObjectConstructor<T> implements ObjectConstructor<T> {
    private final String exceptionMessage;

    ThrowingObjectConstructor(String exceptionMessage) {
      this.exceptionMessage = exceptionMessage;
    }

    @Override
    public T construct() {
      // New exception is created every time to avoid keeping a reference to an exception with
      // potentially long stack trace, causing a memory leak
      // (which would happen if the exception was already created when the
      // `ThrowingObjectConstructor` is created)
      throw new JsonIOException(exceptionMessage);
    }
  }

  private static final class InstanceCreatorConstructor<T> implements ObjectConstructor<T> {
    private final InstanceCreator<T> instanceCreator;
    private final Type type;

    InstanceCreatorConstructor(InstanceCreator<T> instanceCreator, Type type) {
      this.instanceCreator = instanceCreator;
      this.type = type;
    }

    @Override
    public T construct() {
      return instanceCreator.createInstance(type);
    }
  }
}

View on GitHub (pinned to 310ac341f2)

Solutions

  1. Register an InstanceCreator for the interface returning a concrete implementation
  2. Register a TypeAdapter for the interface
  3. Deserialize into a concrete implementation class instead of the interface
  4. Use RuntimeTypeAdapterFactory (from gson-extras) for polymorphic deserialization

Example fix

// before
gson.fromJson(json, Runnable.class);

// after
gsonBuilder.registerTypeAdapter(Runnable.class,
  (InstanceCreator<Runnable>) type -> new MyRunnableImpl());
Defensive patterns

Strategy: validation

Validate before calling

// Check if the target type is an interface before deserializing
Class<?> c = (Class<?>) targetType;
if (c.isInterface()) {
  throw new IllegalArgumentException(
    "Cannot deserialize into interface " + c.getName() + "; register InstanceCreator");
}

Type guard

static boolean isDeserializableWithoutAdapter(Class<?> c) {
  return !c.isInterface() && !Modifier.isAbstract(c.getModifiers());
}

Try / catch

try {
  return gson.fromJson(json, targetInterface);
} catch (JsonIOException e) {
  if (e.getMessage().startsWith("Interfaces can't be instantiated")) {
    // register an InstanceCreator for the interface and retry
    throw new MyParseException("Need InstanceCreator for interface " + targetInterface, e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling gson.fromJson(json, SomeInterface.class) or having an interface-typed field that Gson must populate, where SomeInterface has no registered InstanceCreator or TypeAdapter.

Common situations: Deserializing into interface-typed fields (e.g. List vs ArrayList is fine, but custom interfaces are not); DI-managed types; missing adapter registration; polymorphic type handling without RuntimeTypeAdapterFactory.

Related errors


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