{"record":{"id":"fb04dccac16cb438","repo":"apache/iceberg","slug":"cannot-write-unknown-type","errorCode":null,"errorMessage":"Cannot write unknown type: ","messagePattern":"Cannot write unknown type: ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/SchemaParser.java","lineNumber":159,"sourceCode":"  }\n\n  static void toJson(Type type, JsonGenerator generator) throws IOException {\n    if (type.isPrimitiveType() || type.isVariantType()) {\n      generator.writeString(type.toString());\n    } else {\n      Type.NestedType nested = type.asNestedType();\n      switch (type.typeId()) {\n        case STRUCT:\n          toJson(nested.asStructType(), generator);\n          break;\n        case LIST:\n          toJson(nested.asListType(), generator);\n          break;\n        case MAP:\n          toJson(nested.asMapType(), generator);\n          break;\n        default:\n          throw new IllegalArgumentException(\"Cannot write unknown type: \" + type);\n      }\n    }\n  }\n\n  public static void toJson(Schema schema, JsonGenerator generator) throws IOException {\n    toJson(schema.asStruct(), schema.schemaId(), schema.identifierFieldIds(), generator);\n  }\n\n  public static String toJson(Schema schema) {\n    return toJson(schema, false);\n  }\n\n  public static String toJson(Schema schema, boolean pretty) {\n    return JsonUtil.generate(\n        gen -> toJson(schema.asStruct(), schema.schemaId(), schema.identifierFieldIds(), gen),\n        pretty);\n  }\n","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/SchemaParser.java#L141-L177","documentation":"SchemaParser.toJson(Type, JsonGenerator) serializes a Type by dispatching on its type id (struct, list, map, and primitives). If a type falls through all known cases, it throws this IllegalArgumentException, meaning an unrecognized/unknown Type implementation reached the schema serializer.","triggerScenarios":"Calling SchemaParser.toJson(schema, generator) (directly or via table metadata serialization) with a schema containing a Type implementation the parser does not handle — typically a custom Type implementation or one from a different Iceberg version.","commonSituations":"Custom Type subclasses in embedded/forked builds; mixed Iceberg jar versions where a newer type (e.g. a new variant/unknown type) is serialized by an older parser; test doubles of Type that don't implement the standard hierarchy.","solutions":["Use only standard Iceberg Types (Types.StructType, ListType, MapType, primitive types) in the schema","Align Iceberg versions so the writer's types are known to the parser","If a custom type is required, convert it to a supported standard type before serializing"],"exampleFix":"// before\nSchema schema = new Schema(Arrays.asList(Types.NestedField.optional(1, \"f\", customType)));\nSchemaParser.toJson(schema, generator); // throws\n// after\nType compatible = mapCustomToStandardType(customType); // e.g. Types.StringType.get()\nSchema schema = new Schema(Arrays.asList(Types.NestedField.optional(1, \"f\", compatible)));\nSchemaParser.toJson(schema, generator);","handlingStrategy":"validation","validationCode":"for (Types.NestedField f : schema.columns()) {\n  Preconditions.checkArgument(isStandardType(f.type()), \"Non-standard type on field %s: %s\", f.name(), f.type());\n}\nstatic boolean isStandardType(Type t) {\n  return t instanceof Types.BooleanType || t instanceof Types.IntegerType || t instanceof Types.LongType || t instanceof Types.FloatType || t instanceof Types.DoubleType || t instanceof Types.DateType || t instanceof Types.TimeType || t instanceof Types.TimestampType || t instanceof Types.StringType || t instanceof Types.UUIDType || t instanceof Types.FixedType || t instanceof Types.BinaryType || t instanceof Types.DecimalType || t instanceof Types.ListType || t instanceof Types.MapType || t instanceof Types.StructType;\n}","typeGuard":"static boolean isSerializableType(Type t) {\n  switch (t.typeId()) {\n    case STRUCT: case LIST: case MAP: return true;\n    case BOOLEAN: case INTEGER: case LONG: case FLOAT: case DOUBLE: case DATE: case TIME:\n    case TIMESTAMP: case STRING: case UUID: case FIXED: case BINARY: case DECIMAL: return true;\n    default: return false;\n  }\n}","tryCatchPattern":"try {\n  SchemaParser.toJson(schema, generator);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().startsWith(\"Cannot write unknown type\")) throw new IllegalStateException(\"Schema contains a type unknown to SchemaParser: \" + e.getMessage(), e);\n  throw e;\n}","preventionTips":["Use only Types.* standard type implementations in schemas","Pin one Iceberg version across all modules that build and parse schemas","Convert custom types to standard equivalents before schema serialization"],"tags":["json","serialization","schema"],"backgroundTag":"unsupported-operation","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}