apache/iceberg · error · UnsupportedOperationException

Struct copy cannot be modified

Error message

Struct copy cannot be modified

What it means

StructLikeUtil.copy creates an immutable snapshot copy of a StructLike row; the returned copy's set method deliberately throws UnsupportedOperationException because the copy exists only to hold stable values (e.g. as a map key). Attempting to write into the copy fails.

Solutions

  1. Create a mutable instance (e.g. GenericRecord or the original StructLike) instead of writing to the copy
  2. Copy again from a mutable template: build a new mutable row, set fields, then copy if needed for keying
  3. Read-only accessors (get) are safe; refactor mutation code to operate on the source record before copying

Example fix

// before
StructLike snapshot = StructLikeUtil.copy(type, record);
snapshot.set(0, newValue); // throws
// after
StructLike mutable = new RecordTuple(GenericRecord.create(type));
mutable.set(0, newValue);
StructLike key = StructLikeUtil.copy(type, mutable);
Defensive patterns

Strategy: type-guard

Type guard

boolean isImmutableCopy(StructLike s) {
  try { s.set(0, s.get(0, Object.class)); return false; }
  catch (UnsupportedOperationException e) { return true; }
  catch (Exception e) { return false; }
}

Prevention

When it happens

Trigger: Storing a StructLikeUtil.copy(...) result and later trying to update a field via set(pos, value); reusing a copied row as a mutable record buffer.

Common situations: Using copied rows as dedup/map keys then attempting to overwrite them; code that assumed copy() returned a mutable clone like InternalRecord copy semantics.

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


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/8b460de575b55625. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/apache/iceberg/util/StructLikeUtil.java:64

        } else {
          values[i] = value;
        }
      }
    }

    @Override
    public int size() {
      return values.length;
    }

    @Override
    public <T> T get(int pos, Class<T> javaClass) {
      return javaClass.cast(values[pos]);
    }

    @Override
    public <T> void set(int pos, T value) {
      throw new UnsupportedOperationException("Struct copy cannot be modified");
    }
  }
}

View on GitHub (pinned to 86d9c8fc54)