{"record":{"id":"6ac9977954b280da","repo":"apache/iceberg","slug":"unknown-type-for-binary-field-type-name-byte-6ac997","errorCode":null,"errorMessage":"Unknown type for binary field. Type name: \" + bytes.getClass().getName()","messagePattern":"Unknown type for binary field\\. Type name: \" \\+ bytes\\.getClass\\(\\)\\.getName\\(\\)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/source/StructInternalRow.java","lineNumber":201,"sourceCode":"    CharSequence seq = struct.get(ordinal, CharSequence.class);\n    return UTF8String.fromString(seq.toString());\n  }\n\n  @Override\n  public byte[] getBinary(int ordinal) {\n    return isNullAt(ordinal) ? null : getBinaryInternal(ordinal);\n  }\n\n  private byte[] getBinaryInternal(int ordinal) {\n    Object bytes = struct.get(ordinal, Object.class);\n\n    // should only be either ByteBuffer or byte[]\n    if (bytes instanceof ByteBuffer) {\n      return ByteBuffers.toByteArray((ByteBuffer) bytes);\n    } else if (bytes instanceof byte[]) {\n      return (byte[]) bytes;\n    } else {\n      throw new IllegalStateException(\n          \"Unknown type for binary field. Type name: \" + bytes.getClass().getName());\n    }\n  }\n\n  @Override\n  public CalendarInterval getInterval(int ordinal) {\n    throw new UnsupportedOperationException(\"Unsupported type: interval\");\n  }\n\n  @Override\n  public InternalRow getStruct(int ordinal, int numFields) {\n    return isNullAt(ordinal) ? null : getStructInternal(ordinal);\n  }\n\n  private InternalRow getStructInternal(int ordinal) {\n    return new StructInternalRow(\n        type.fields().get(ordinal).type().asStructType(), struct.get(ordinal, StructLike.class));\n  }","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/source/StructInternalRow.java#L183-L219","documentation":"StructInternalRow.getBinaryInternal materializes a Spark BINARY column from the underlying field, which Iceberg stores as either ByteBuffer or byte[]. Any other Java class means the stored object doesn't match the declared binary type, so it throws IllegalStateException with the actual class name.","triggerScenarios":"Reading a column declared as Spark BinaryType while the Iceberg struct actually contains e.g. String, ByteString, or a heap ByteBuffer subtype that failed boxing expectations — a schema/value type mismatch between producer and reader.","commonSituations":"Custom row wrappers storing non-standard types in the struct; schema drift where the field changed type after being written; wrong expected schema in a custom scan.","solutions":["Ensure the producer stores ByteBuffer or byte[] for binary fields","Check the class name in the message and convert at the producer (e.g. wrap byte[] in ByteBuffer or call array())","Verify the expected Spark schema matches the table's Iceberg type (BinaryType vs StringType mixups are common)","Upgrade/rebuild against the same Iceberg version used to write, so Java class mappings agree"],"exampleFix":"// before\nbyte[] b = row.getBinaryInternal(ordinal); // stored String -> IllegalStateException\n// after\n// fix producer:\nstruct.set(ordinal, ByteBuffer.wrap(stringValue.getBytes(StandardCharsets.UTF_8)));","handlingStrategy":"type-guard","validationCode":"Object v = struct.get(pos, javaClass);\nif (!(v instanceof ByteBuffer) && !(v instanceof byte[])) {\n  throw new IllegalStateException(\"expected ByteBuffer or byte[] for binary field, got \" + v.getClass());\n}","typeGuard":"boolean isBinaryBacked(Object v) { return v instanceof ByteBuffer || v instanceof byte[]; }","tryCatchPattern":"try { byte[] b = row.getBinaryInternal(ordinal); } catch (IllegalStateException e) { /* convert or fix the producer to store ByteBuffer/byte[] */ }","preventionTips":["Store binary columns as ByteBuffer or byte[] in custom struct wrappers","Don't declare a column BinaryType if values were written as strings","Verify schema compatibility after table type evolutions"],"tags":["spark","internalrow","type-mismatch","binary"],"backgroundTag":"type-mismatch","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T21:17:11.552Z"}