apache/iceberg · error · IllegalArgumentException
Cannot write unknown type:
Error message
Cannot write unknown type:
What it means
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.
Source
Thrown at core/src/main/java/org/apache/iceberg/SchemaParser.java:159
}
static void toJson(Type type, JsonGenerator generator) throws IOException {
if (type.isPrimitiveType() || type.isVariantType()) {
generator.writeString(type.toString());
} else {
Type.NestedType nested = type.asNestedType();
switch (type.typeId()) {
case STRUCT:
toJson(nested.asStructType(), generator);
break;
case LIST:
toJson(nested.asListType(), generator);
break;
case MAP:
toJson(nested.asMapType(), generator);
break;
default:
throw new IllegalArgumentException("Cannot write unknown type: " + type);
}
}
}
public static void toJson(Schema schema, JsonGenerator generator) throws IOException {
toJson(schema.asStruct(), schema.schemaId(), schema.identifierFieldIds(), generator);
}
public static String toJson(Schema schema) {
return toJson(schema, false);
}
public static String toJson(Schema schema, boolean pretty) {
return JsonUtil.generate(
gen -> toJson(schema.asStruct(), schema.schemaId(), schema.identifierFieldIds(), gen),
pretty);
}
View on GitHub (pinned to 86d9c8fc54)
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
Example fix
// before Schema schema = new Schema(Arrays.asList(Types.NestedField.optional(1, "f", customType))); SchemaParser.toJson(schema, generator); // throws // after Type compatible = mapCustomToStandardType(customType); // e.g. Types.StringType.get() Schema schema = new Schema(Arrays.asList(Types.NestedField.optional(1, "f", compatible))); SchemaParser.toJson(schema, generator);
Defensive patterns
Strategy: validation
Validate before calling
for (Types.NestedField f : schema.columns()) {
Preconditions.checkArgument(isStandardType(f.type()), "Non-standard type on field %s: %s", f.name(), f.type());
}
static boolean isStandardType(Type t) {
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;
} Type guard
static boolean isSerializableType(Type t) {
switch (t.typeId()) {
case STRUCT: case LIST: case MAP: return true;
case BOOLEAN: case INTEGER: case LONG: case FLOAT: case DOUBLE: case DATE: case TIME:
case TIMESTAMP: case STRING: case UUID: case FIXED: case BINARY: case DECIMAL: return true;
default: return false;
}
} Try / catch
try {
SchemaParser.toJson(schema, generator);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Cannot write unknown type")) throw new IllegalStateException("Schema contains a type unknown to SchemaParser: " + e.getMessage(), e);
throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Unsupported task type:
- Cannot parse type from json:
- Cannot parse default as a %s value: %s
- Type: %s is not supported
- Failed to write json for: %s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/fb04dccac16cb438.
Report an issue: GitHub.