{"record":{"id":"5f6a59e868308358","repo":"apache/druid","slug":"failed-to-serialize-tabledefn","errorCode":null,"errorMessage":"Failed to serialize TableDefn","messagePattern":"Failed to serialize TableDefn","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"server/src/main/java/org/apache/druid/catalog/model/CatalogUtils.java","lineNumber":185,"sourceCode":"    return String.join(\"\\n\", lines) + \"\\n\";\n  }\n\n  /**\n   * Catalog-specific quick & easy implementation of {@code toString()} for objects\n   * which are primarily representations of JSON objects. Use only for cases where the\n   * {@code toString()} is for debugging. Also, assumes that the\n   * type can serialized using the default mapper: this trick doesn't work for types that\n   * require custom Jackson extensions. The catalog, however, has a simple type\n   * hierarchy, which is not extended via extensions, and so the default object mapper is\n   * fine.\n   */\n  public static String toString(Object obj)\n  {\n    try {\n      return DefaultObjectMapper.INSTANCE.writerWithDefaultPrettyPrinter().writeValueAsString(obj);\n    }\n    catch (JsonProcessingException e) {\n      throw new ISE(\"Failed to serialize TableDefn\");\n    }\n  }\n\n  public static <T> List<T> concatLists(\n      @Nullable final List<T> base,\n      @Nullable final List<T> additions\n  )\n  {\n    return Stream\n        .of(base, additions)\n        .filter(Objects::nonNull)\n        .flatMap(Collection::stream)\n        .collect(Collectors.toList());\n  }\n\n  /**\n   * Get a string parameter that can either be null or non-blank.\n   */","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/server/src/main/java/org/apache/druid/catalog/model/CatalogUtils.java#L167-L203","documentation":"Thrown by CatalogUtils.toString(Object) when the pretty-printer fails to serialize the given object (usually a TableDefn) to JSON, i.e. JsonProcessingException. Since definition objects are expected to be plain JSON-friendly POJOs, a failure here indicates the object contains non-serializable content (self-references, invalid types) or a Jackson configuration problem.","triggerScenarios":"Calling toString() on a TableDefn (or passing a definition object to CatalogUtils.toString) whose fields cannot be mapped to JSON: e.g. a field holding an object with no properties, an unserializable type added via subclassing, or a corrupted object graph built outside normal deserialization paths.","commonSituations":"Custom TableDefn subclasses adding non-POJO fields, objects deserialized into unexpected shapes (raw Maps containing non-JSON values), debugging/logging code calling toString on partially constructed definitions.","solutions":["Check the offending object's fields for types Jackson cannot serialize; annotate or remove them (@JsonIgnore, serializable types)","Inspect the swallowed JsonProcessingException by reproducing with DefaultObjectMapper.INSTANCE.writeValueAsString in a debugger/log (note the ISE drops the cause)","Ensure custom definition subclasses keep fields JSON-friendly and registered with the object mapper"],"exampleFix":"// before\nclass MyDefn extends TableDefn {\n  private transient java.io.InputStream data; // non-serializable field\n}\n// after\nclass MyDefn extends TableDefn {\n  @JsonIgnore\n  private transient java.io.InputStream data;\n}","handlingStrategy":"try-catch","validationCode":"// pre-check serializability before relying on toString\ntry {\n  String s = DefaultObjectMapper.INSTANCE.writeValueAsString(obj);\n} catch (JsonProcessingException e) {\n  log.error(\"Object {} is not JSON-serializable\", obj.getClass(), e);\n}","typeGuard":null,"tryCatchPattern":"try {\n  String s = CatalogUtils.toString(defn);\n} catch (IllegalStateException e) {\n  if (\"Failed to serialize TableDefn\".equals(e.getMessage())) {\n    log.error(\"TableDefn {} has non-serializable fields\", defn.getId());\n  }\n}","preventionTips":["Keep TableDefn subclasses to plain JSON-friendly fields; use @JsonIgnore for the rest","Never attach streams, connections, or lambdas to definition objects","Reproduce serialization failures in tests with DefaultObjectMapper to see the real cause"],"tags":["json","serialization","catalog"],"backgroundTag":"json-marshal-failed","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}