eclipse-vertx/vert.x · error · IllegalArgumentException

Invalid type for shareddata data structure: ${obj.getClass()

Error message

Invalid type for shareddata data structure: ${obj.getClass().getName()}

What it means

Vert.x SharedData only allows values that can be safely shared across threads/cluster members. Checker.checkType validates that an object placed into a shared data structure is Serializable, Shareable, or ClusterSerializable; otherwise it throws IllegalArgumentException naming the offending class.

Source

Thrown at vertx-core/src/main/java/io/vertx/core/shareddata/impl/Checker.java:57

    .add(String.class)
    .add(Integer.class)
    .add(Long.class)
    .add(Boolean.class)
    .add(Double.class)
    .add(Float.class)
    .add(Short.class)
    .add(Byte.class)
    .add(Character.class)
    .add(BigInteger.class)
    .add(BigDecimal.class)
    .build()
    .collect(toSet());

  static void checkType(Object obj) {
    Objects.requireNonNull(obj, "null not allowed for shareddata data structure");
    // All immutables and byte arrays are Serializable by the platform
    if (!(obj instanceof Serializable || obj instanceof Shareable || obj instanceof ClusterSerializable)) {
      throw new IllegalArgumentException("Invalid type for shareddata data structure: " + obj.getClass().getName());
    }
  }

  @SuppressWarnings("unchecked")
  static <T> T copyIfRequired(T obj) {
    Object result;
    if (obj == null) {
      // Happens with putIfAbsent
      result = null;
    } else if (IMMUTABLE_TYPES.contains(obj.getClass())) {
      result = obj;
    } else if (obj instanceof byte[]) {
      result = copyByteArray((byte[]) obj);
    } else if (obj instanceof Shareable) {
      result = ((Shareable) obj).copy();
    } else if (obj instanceof ClusterSerializable) {
      result = copyClusterSerializable((ClusterSerializable) obj);
    } else if (obj instanceof Serializable) {

View on GitHub (pinned to fb308bd8c3)

Solutions

  1. Make the stored class implement Serializable (or Shareable for mutable types with an efficient copy strategy).
  2. If the type is an array-like payload, store byte[] or a Buffer (Buffer is ClusterSerializable).
  3. Store a serializable representation (JSON via JsonObject, a String, or a primitive wrapper) instead of the raw object.
  4. If the object must stay non-serializable, keep it in an ordinary ConcurrentMap rather than SharedData.

Example fix

// before
localMap.put("cfg", new MyConfig()); // MyConfig not serializable -> IllegalArgumentException
// after
public class MyConfig implements Serializable { ... }
localMap.put("cfg", new MyConfig());
Defensive patterns

Strategy: validation

Validate before calling

static boolean isShareableType(Object o) {
  return o instanceof java.io.Serializable
      || o instanceof io.vertx.core.shareddata.Shareable
      || o instanceof io.vertx.core.cluster.ClusterSerializable;
}
if (!isShareableType(value)) throw new IllegalArgumentException("cannot store " + value.getClass() + " in shared data");

Type guard

static boolean isShareableType(Object o) {
  return o instanceof java.io.Serializable
      || o instanceof io.vertx.core.shareddata.Shareable
      || o instanceof io.vertx.core.cluster.ClusterSerializable;
}

Try / catch

try {
  map.put(key, value);
} catch (IllegalArgumentException e) {
  if (e.getMessage().startsWith("Invalid type")) {
    throw new IllegalStateException("Value type " + value.getClass().getName() + " is not shareable");
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling put/putForEviction on a LocalMap or an AsyncMap with a key or value whose class implements none of java.io.Serializable, io.vertx.core.shareddata.Shareable, or io.vertx.core.cluster.ClusterSerializable (e.g. a POJO without implements Serializable).

Common situations: Developers put arbitrary domain objects (config beans, builders like java.lang.Object graphs, non-serializable library types) into a LocalMap or cluster-wide AsyncMap; or after a refactor the value class lost its Serializable interface.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06). Data as JSON: /api/errors/3c48395cd000a7bf. Report an issue: GitHub.