apache/iceberg · error · UnsupportedOperationException
Can't modify an empty struct
Error message
Can't modify an empty struct
What it means
EmptyStructLike represents a zero-field struct (unpartitioned data). set() always throws because there is no field to write; mutating it indicates the caller is treating the shared empty placeholder as a writable record.
Source
Thrown at api/src/main/java/org/apache/iceberg/EmptyStructLike.java:45
private EmptyStructLike() {}
static EmptyStructLike get() {
return INSTANCE;
}
@Override
public int size() {
return 0;
}
@Override
public <T> T get(int pos, Class<T> javaClass) {
throw new UnsupportedOperationException("Can't retrieve values from an empty struct");
}
@Override
public <T> void set(int pos, T value) {
throw new UnsupportedOperationException("Can't modify an empty struct");
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
return other != null && getClass() == other.getClass();
}
@Override
public int hashCode() {
return 0;
}
@Override
public String toString() {View on GitHub (pinned to 86d9c8fc54)
Solutions
- Guard the write path: if partitionType().fields().isEmpty(), skip the set loop
- Use a real writable StructLike (e.g. a Record or wrapper) sized to the partition type when fields exist
- Never write into the shared EmptyStructLike instance; it is a read-only singleton by design
Example fix
// before
for (int i = 0; i < fields.size(); i++) {
struct.set(i, values.get(i));
}
// after
if (!(struct instanceof EmptyStructLike)) {
for (int i = 0; i < fields.size(); i++) {
struct.set(i, values.get(i));
}
} Defensive patterns
Strategy: type-guard
Validate before calling
if (struct instanceof EmptyStructLike) { return; } Type guard
boolean isWritable(StructLike s) {
return !(s instanceof EmptyStructLike);
} Try / catch
try {
struct.set(pos, value);
} catch (UnsupportedOperationException e) {
// ignore: unpartitioned empty struct has nothing to write
} Prevention
- Skip write loops for empty partition specs
- Treat EmptyStructLike as a read-only singleton
- Branch on spec.isUnpartitioned() before writing partition fields
When it happens
Trigger: Calling set(pos, value) on EmptyStructLike, e.g. when copying partition values into a StructLike buffer for a table with an empty partition spec, or writer code that unconditionally writes all projected positions.
Common situations: Custom appender/writer code that copies projected fields into a partition StructLike without checking whether the spec is unpartitioned; refactoring that replaced a real StructLike with the empty placeholder.
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
- Can't retrieve values from an empty struct
- %s doesn't implement cleanupLevel
- %s doesn't implement cleanExpiredMetadata
- Does not support schema getter
- %s does not implement deleteFile
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/de8df939d7305cd4.
Report an issue: GitHub.