apache/iceberg · error · UnsupportedOperationException
Unsupported content:
Error message
Unsupported content:
What it means
When building the DeleteFileIndex, each delete file is dispatched by its FileContent. POSITION_DELETES and EQUALITY_DELETES are handled; any other content (which should not appear in a delete index) hits the default branch and throws UnsupportedOperationException with the file's content value.
Source
Thrown at core/src/main/java/org/apache/iceberg/DeleteFileIndex.java:554
PartitionMap<EqualityDeletes> eqDeletesByPartition = PartitionMap.create(specsById);
PartitionMap<PositionDeletes> posDeletesByPartition = PartitionMap.create(specsById);
Map<String, PositionDeletes> posDeletesByPath = Maps.newHashMap();
Map<String, DeleteFile> dvByPath = Maps.newHashMap();
for (DeleteFile file : files) {
switch (file.content()) {
case POSITION_DELETES:
if (ContentFileUtil.isDV(file)) {
add(dvByPath, file);
} else {
add(posDeletesByPath, posDeletesByPartition, file);
}
break;
case EQUALITY_DELETES:
add(globalDeletes, eqDeletesByPartition, file, fieldLookup);
break;
default:
throw new UnsupportedOperationException("Unsupported content: " + file.content());
}
ScanMetricsUtil.indexedDeleteFile(scanMetrics, file);
}
return new DeleteFileIndex(
globalDeletes.isEmpty() ? null : globalDeletes,
eqDeletesByPartition.isEmpty() ? null : eqDeletesByPartition,
posDeletesByPartition.isEmpty() ? null : posDeletesByPartition,
posDeletesByPath.isEmpty() ? null : posDeletesByPath,
dvByPath.isEmpty() ? null : dvByPath,
specsById.isEmpty() ? null : specsById);
}
private void add(Map<String, DeleteFile> dvByPath, DeleteFile dv) {
String path = dv.referencedDataFile();
DeleteFile existingDV = dvByPath.putIfAbsent(path, dv);
if (existingDV != null) {
throw new ValidationException(View on GitHub (pinned to 86d9c8fc54)
Solutions
- Find the offending file/content value in the message and inspect its manifest.
- Regenerate or rewrite the affected manifest with valid delete content values.
- Ensure only delete manifests (position/equality) are passed to the delete index.
- Validate metadata producers — content must be 1 or 2 for delete files.
Example fix
// before index.addFiles(dataManifestEntries); // includes DATA files // after index.addFiles(entries.filter(e -> e.file().content() != FileContent.DATA));
Defensive patterns
Strategy: validation
Validate before calling
entries.forEach(e -> Preconditions.check(
e.file().content() == FileContent.POSITION_DELETES || e.file().content() == FileContent.EQUALITY_DELETES,
"non-delete content in delete index: " + e.file().content())); Try / catch
try { DeleteFileIndex idx = DeleteFileIndex.buildFor(...); } catch (UnsupportedOperationException e) {
LOG.error("bad content value", e);
throw e;
} Prevention
- Only feed delete manifests to DeleteFileIndex.
- Validate metadata written by external tools (content must be 1 or 2).
- Guard against metadata corruption with round-trip tests.
When it happens
Trigger: Constructing DeleteFileIndex.build with a delete manifest entry whose content is DATA (0) or an unknown/invalid content value — e.g. corrupt metadata, wrong manifest passed in, or a spec-version mismatch producing misread content.
Common situations: Corrupted or hand-edited manifests; custom catalog tooling writing invalid content values; reading metadata written by a nonconformant producer.
Related errors
- Failed to close
- Unsupported delete granularity: <granularity>
- Unknown delete file content:
- Invalid distribution mode: %s
- Invalid file format: %s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/67479b06afc9d901.
Report an issue: GitHub.