apache/iceberg · error · UnsupportedOperationException

Expected delete file

Error message

Expected delete file %s to start with prefix: %s

What it means

Thrown by RewriteTablePathUtil.rewritePositionDelete when a position delete file's location does not start with sourcePrefix. The rewriter must map every delete file path from the old table location to the new one and cannot handle files outside the source prefix.

Solutions

  1. Correct the sourcePrefix argument so it matches the actual delete file locations.
  2. Check the delete file path in the message and relocate it under the source prefix before rewriting.
  3. Expire/delete orphan delete files referencing stale locations before the rewrite.

Example fix

// before
String prefix = "s3://bucket/db/table"; // delete files actually under s3://bucket/warehouse/db/table
// after
String prefix = "s3://bucket/warehouse/db/table";
Defensive patterns

Strategy: validation

Validate before calling

for (DeleteFile f : allDeleteFiles(table)) {
  Preconditions.checkArgument(f.location().startsWith(sourcePrefix), "outside prefix: " + f.location());
}

Type guard

boolean underPrefix(String loc, String prefix) { return loc != null && loc.startsWith(prefix); }

Try / catch

try { rewritePositionDelete(...); } catch (UnsupportedOperationException e) { /* correct prefix and retry */ }

Prevention

When it happens

Trigger: Rewriting table path metadata when deleteFile.location() (a position delete file or DV) does not start with the given sourcePrefix — typically due to a wrong prefix argument or files left over from a prior table location.

Common situations: Table relocation/clone where delete files were written under an older path; typo in sourcePrefix; table registered from external location then rewritten.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at core/src/main/java/org/apache/iceberg/RewriteTablePathUtil.java:748

   * @param io file io
   * @param spec spec of delete file
   * @param sourcePrefix source prefix that will be replaced
   * @param targetPrefix target prefix to replace it
   * @param posDeleteReaderWriter class to read and write position delete files
   * @return the size in bytes of the rewritten file
   */
  public static long rewritePositionDelete(
      DeleteFile deleteFile,
      OutputFile outputFile,
      FileIO io,
      PartitionSpec spec,
      String sourcePrefix,
      String targetPrefix,
      PositionDeleteReaderWriter posDeleteReaderWriter)
      throws IOException {
    String path = deleteFile.location();
    if (!path.startsWith(sourcePrefix)) {
      throw new UnsupportedOperationException(
          String.format("Expected delete file %s to start with prefix: %s", path, sourcePrefix));
    }

    // DV files (Puffin format for v3+) need special handling to rewrite internal blob metadata
    if (ContentFileUtil.isDV(deleteFile)) {
      return rewriteDVFile(deleteFile, outputFile, io, sourcePrefix, targetPrefix);
    }

    // For non-DV position delete files (v2), rewrite using the reader/writer
    InputFile sourceFile = io.newInputFile(path);
    try (CloseableIterable<Record> reader =
        posDeleteReaderWriter.reader(sourceFile, deleteFile.format(), spec)) {
      Record record = null;
      CloseableIterator<Record> recordIt = reader.iterator();

      if (recordIt.hasNext()) {
        record = recordIt.next();
      }

View on GitHub (pinned to 86d9c8fc54)