{"record":{"id":"c3769828dcd7bf7f","repo":"eclipse-vertx/vert.x","slug":"illegal-type-in-json-o-getclass","errorCode":null,"errorMessage":"Illegal type in Json: ${o.getClass()}","messagePattern":"Illegal type in Json: (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"vertx-core/src/main/java/io/vertx/core/json/impl/JsonUtil.java","lineNumber":71,"sourceCode":"    if (val instanceof Map) {\n      val = new JsonObject((Map) val);\n    } else if (val instanceof List) {\n      val = new JsonArray((List) val);\n    } else if (val instanceof Instant) {\n      val = ISO_INSTANT.format((Instant) val);\n    } else if (val instanceof byte[]) {\n      val = BASE64_ENCODER.encodeToString((byte[]) val);\n    } else if (val instanceof Buffer) {\n      val = BASE64_ENCODER.encodeToString(((Buffer) val).getBytes());\n    } else if (val instanceof Enum) {\n      val = ((Enum) val).name();\n    }\n\n    return val;\n  }\n\n  public static final Function<Object, ?> DEFAULT_CLONER = o -> {\n    throw new IllegalStateException(\"Illegal type in Json: \" + o.getClass());\n  };\n\n  @SuppressWarnings(\"unchecked\")\n  public static Object deepCopy(Object val, Function<Object, ?> copier) {\n    if (val == null) {\n      // OK\n    } else if (val instanceof Number) {\n      // OK\n    } else if (val instanceof Boolean) {\n      // OK\n    } else if (val instanceof String) {\n      // OK\n    } else if (val instanceof Character) {\n      // OK\n    } else if (val instanceof CharSequence) {\n      // CharSequences are not immutable, so we force toString() to become immutable\n      val = val.toString();\n    } else if (val instanceof Shareable) {","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/eclipse-vertx/vert.x/blob/fb308bd8c3f12c79f4ae89bef67fadf6c80d036e/vertx-core/src/main/java/io/vertx/core/json/impl/JsonUtil.java#L53-L89","documentation":"DEFAULT_CLONER is the fallback cloner used by JsonUtil.deepCopy when a value of an unsupported type is encountered during a deep copy of a JSON tree. Hitting it means the map/list being copied contains an object that is neither null, Map, List, String, Number, Boolean, nor byte[] (e.g. an Instant, POJO, or byte-buffer leaked into the JSON structure).","triggerScenarios":"Calling JsonObject.copy() / JsonUtil.deepCopy (or put of nested structures then copying) when the JsonObject was populated with non-JSON-native values such as java.time.Instant, java.math.BigDecimal is fine but a custom POJO, byte buffer wrapper, or Map with exotic value types is not.","commonSituations":"Developers put raw domain objects (POJOs, Instants, enums) into a JsonObject via mapValue converters that skipped wrapping; then a copy/serialization path walks the tree and cannot clone the foreign value. Often surfaces after upgrading Vert.x where cloner behavior changed.","solutions":["Find the offending value type reported in the message (e.g. class java.time.Instant).","Convert the value to a JSON-native type before putting it: instant.toString(), pojo.toJsonObject(), buffer.getBytes() for binary.","Use JsonPojo/ValueConverter mappers (JsonMapper) so POJOs are encoded on put.","If the type must be supported, register a custom cloner via JsonUtil options instead of relying on DEFAULT_CLONER."],"exampleFix":"// before\njsonObject.put(\"createdAt\", Instant.now());\njsonObject.copy(); // IllegalStateException: Illegal type in Json: class java.time.Instant\n// after\njsonObject.put(\"createdAt\", Instant.now().toString());","handlingStrategy":"type-guard","validationCode":"for (Map.Entry<String, Object> e : map.entrySet()) {\n  if (!isJsonNative(e.getValue())) throw new IllegalStateException(\"Non-JSON value at key: \" + e.getKey());\n}","typeGuard":"static boolean isJsonNative(Object v) {\n  return v == null || v instanceof String || v instanceof Number || v instanceof Boolean\n    || v instanceof Map || v instanceof List || v instanceof byte[];\n}","tryCatchPattern":"try {\n  JsonObject copy = jsonObject.copy();\n} catch (IllegalStateException e) {\n  // message names the offending class; convert it and retry\n}","preventionTips":["Only put JSON-native values (String, Number, Boolean, null, Map, List, byte[]) into JsonObject.","Convert Instant/Date to ISO strings and POJOs via their mappers on insert.","Review any code that stores arbitrary Object in JsonObject before calling copy() or serializing."],"tags":["json","clone","type-error"],"backgroundTag":"incompatible-source-type","analyzedSha":"fb308bd8c3f12c79f4ae89bef67fadf6c80d036e","analyzedAt":"2026-09-06T11:37:12.241Z","contentChangedAt":"2026-09-06T11:37:12.241Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}