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
- Correct the sourcePrefix argument so it matches the actual delete file locations.
- Check the delete file path in the message and relocate it under the source prefix before rewriting.
- 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
- Verify sourcePrefix equals the source table location
- Expire stale delete files before migration
- Log delete file locations during relocation planning
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
- Expected delete file to be under the source prefix: but…
- Path does not start with
- ALTER VIEW AS is not supported. Use CREATE OR REPLACE VIEW…
- apply(value) is deprecated, use bind(Type).apply(value)
- apply(value) is deprecated, use bind(Type).apply(value)
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)