apache/iceberg · error · UnsupportedOperationException

Position delete writer does not support row data

Error message

Position delete writer does not support row data

What it means

ORC's DeleteWriteBuilder for position deletes only writes the (path, pos) schema. Unlike Parquet, ORC position delete writers do not support storing the deleted row alongside the position, so if a row schema (rowSchema) was supplied the builder throws UnsupportedOperationException.

Solutions

  1. Do not call rowSchema() for ORC position delete writers; write position-only deletes
  2. Switch the table's format to Parquet if row-in-position-delete is required
  3. Remove the rowSchema configuration from the delete write path

Example fix

// before
deleteWriteBuilder.rowSchema(table.schema()); // throws for ORC
// after
deleteWriteBuilder.spec(spec).partition(partition); // position-only delete, no rowSchema
Defensive patterns

Strategy: type-guard

Validate before calling

if (format == FileFormat.ORC && rowSchema != null) {
  throw new IllegalArgumentException("rowSchema is not supported for ORC position deletes");
}

Type guard

boolean orcRowDeleteSupported(FileFormat f) { return f != FileFormat.ORC; }

Try / catch

try {
  appender = deleteWriteBuilder.build();
} catch (UnsupportedOperationException e) {
  if (e.getMessage().contains("does not support row data")) {
    throw new IllegalStateException("Write position-only deletes for ORC (drop rowSchema)", e);
  } throw e;
}

Prevention

When it happens

Trigger: Calling DeleteWriteBuilder.rowSchema(...) (or an API that sets it) before building an ORC position delete writer — i.e. writing format-version 2 position deletes with row data on ORC files.

Common situations: Porting a Parquet delete-writer code path to ORC; generic write pipelines that set rowSchema for all formats; using the merge-on-read row-in-delete feature with an ORC table.

Related errors


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

Appendix: source

Thrown at orc/src/main/java/org/apache/iceberg/orc/ORC.java:649

          FileFormat.ORC,
          location,
          spec,
          partition,
          keyMetadata,
          sortOrder,
          equalityFieldIds);
    }

    public <T> PositionDeleteWriter<T> buildPositionWriter() {
      Preconditions.checkState(
          equalityFieldIds == null, "Cannot create position delete file using delete field ids");
      Preconditions.checkArgument(
          spec != null, "Spec must not be null when creating position delete writer");
      Preconditions.checkArgument(
          spec.isUnpartitioned() || partition != null,
          "Partition must not be null for partitioned writes");
      if (rowSchema != null) {
        throw new UnsupportedOperationException("Position delete writer does not support row data");
      }

      meta("delete-type", "position");

      appenderBuilder.schema(DeleteSchemaUtil.pathPosSchema());

      // the createWriterFunc is ignored, since only the path and position are written
      appenderBuilder.createWriterFunc(
          (schema, typeDescription) ->
              GenericOrcWriters.positionDelete(
                  GenericOrcWriter.buildWriter(schema, typeDescription), Function.identity()));

      appenderBuilder.createContextFunc(WriteBuilder.Context::deleteContext);

      return new PositionDeleteWriter<>(
          appenderBuilder.build(), FileFormat.ORC, location, spec, partition, keyMetadata);
    }
  }

View on GitHub (pinned to 86d9c8fc54)