{"record":{"id":"d878bfe05ad1582c","repo":"apache/iceberg","slug":"cannot-write-unknown-string-type","errorCode":null,"errorMessage":"Cannot write unknown string type: ","messagePattern":"Cannot write unknown string type: ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/avro/ValueWriters.java","lineNumber":253,"sourceCode":"\n  private static class StringWriter implements ValueWriter<Object> {\n    private static final StringWriter INSTANCE = new StringWriter();\n\n    private StringWriter() {}\n\n    @Override\n    public void write(Object s, Encoder encoder) throws IOException {\n      // use getBytes because it may return the backing byte array if available.\n      // otherwise, it copies to a new byte array, which is still cheaper than Avro\n      // calling toString, which incurs encoding costs\n      if (s instanceof Utf8) {\n        encoder.writeString((Utf8) s);\n      } else if (s instanceof String) {\n        encoder.writeString(new Utf8((String) s));\n      } else if (s == null) {\n        throw new IllegalArgumentException(\"Cannot write null to required string column\");\n      } else {\n        throw new IllegalArgumentException(\n            \"Cannot write unknown string type: \" + s.getClass().getName() + \": \" + s);\n      }\n    }\n  }\n\n  private static class Utf8Writer implements ValueWriter<Utf8> {\n    private static final Utf8Writer INSTANCE = new Utf8Writer();\n\n    private Utf8Writer() {}\n\n    @Override\n    public void write(Utf8 s, Encoder encoder) throws IOException {\n      encoder.writeString(s);\n    }\n  }\n\n  private static class UUIDWriter implements ValueWriter<UUID> {\n    private static final ThreadLocal<ByteBuffer> BUFFER =","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/avro/ValueWriters.java#L235-L271","documentation":"The same string writer only knows how to encode Avro Utf8 and java.lang.String; any other object type found in the column triggers this IllegalArgumentException including the runtime class name and value. It catches type leakage from upstream data sources.","triggerScenarios":"Writing CharSequence subclasses (e.g. StringBuilder), or custom string-like types, into a string column; passing objects from another serialization library (e.g. protobuf ByteString) without conversion.","commonSituations":"Reading with a different engine/row format then writing with the generic writer without conversion; dependency changes returning different CharSequence implementations.","solutions":["Convert the value to java.lang.String (String.valueOf) before writing","If using Avro GenericData, ensure the column value is Utf8","Check upstream mapping so only String/Utf8 reach the string writer"],"exampleFix":"// before\nwriter.write(stringBuilderValue, encoder);\n// after\nwriter.write(stringBuilderValue.toString(), encoder);","handlingStrategy":"type-guard","validationCode":"if (!(v instanceof String || v instanceof Utf8)) throw new IllegalArgumentException(\"string column got \" + v.getClass().getName());","typeGuard":"String asString(Object v) { return v instanceof Utf8 ? ((Utf8) v).toString() : (v instanceof String ? (String) v : v.toString()); }","tryCatchPattern":"try { writer.writeValue(encoder, v); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith(\"Cannot write unknown string type\")) { /* convert to String upstream */ } else throw e; }","preventionTips":["Normalize CharSequence wrappers with toString() before writing","Avoid passing protobuf/other-library string types directly","Add mapping tests for all incoming data types"],"tags":["avro","type-mismatch","write"],"backgroundTag":"type-mismatch","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}