apache/iceberg · error · IllegalArgumentException
Unknown manifest content: ${content}
Error message
Unknown manifest content: ${content} What it means
RewriteManifestsSparkAction.loadManifests selects manifest lists from a snapshot by manifest content type (DATA or DELETES). If the snapshot's ManifestContent enum is anything else, it throws IllegalArgumentException. In practice this only occurs with future/unknown content types from a newer spec version.
Source
Thrown at spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/actions/RewriteManifestsSparkAction.java:371
if (currentSnapshot == null) {
return ImmutableList.of();
}
List<ManifestFile> manifests = loadManifests(content, currentSnapshot);
return manifests.stream()
.filter(manifest -> manifest.partitionSpecId() == spec.specId() && predicate.test(manifest))
.collect(Collectors.toList());
}
private List<ManifestFile> loadManifests(ManifestContent content, Snapshot snapshot) {
switch (content) {
case DATA:
return snapshot.dataManifests(table.io());
case DELETES:
return snapshot.deleteManifests(table.io());
default:
throw new IllegalArgumentException("Unknown manifest content: " + content);
}
}
private int targetNumManifests(long totalSizeBytes) {
return (int) ((totalSizeBytes + targetManifestSizeBytes - 1) / targetManifestSizeBytes);
}
private long totalSizeBytes(Iterable<ManifestFile> manifests) {
long totalSizeBytes = 0L;
for (ManifestFile manifest : manifests) {
ValidationException.check(
hasFileCounts(manifest), "No file counts in manifest: %s", manifest.path());
totalSizeBytes += manifest.length();
}
return totalSizeBytes;
}View on GitHub (pinned to 86d9c8fc54)
Solutions
- Upgrade the Spark Iceberg runtime to match (or exceed) the version that wrote the table metadata.
- Rewrite from a snapshot/version that only contains DATA and DELETES manifests (rollback or rewrite from an earlier version).
- Check the table's snapshots for unexpected manifest content with SparkActions before running rewrite.
Example fix
// before sparkActions.rewriteManifests(table).execute(); // after // upgrade runtime first, then: sparkActions.rewriteManifests(table).useSnapshotId(validSnapshotId).execute();
Defensive patterns
Strategy: type-guard
Validate before calling
boolean ok = table.currentSnapshot() == null || table.currentSnapshot().allManifests(table.io()).stream().allMatch(m -> m.content() == ManifestContent.DATA || m.content() == ManifestContent.DELETES);
Type guard
if (manifest.content() != ManifestContent.DATA && manifest.content() != ManifestContent.DELETES) { throw new IllegalArgumentException(...); } Try / catch
try { action.execute(); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith("Unknown manifest content")) { /* upgrade runtime / use different snapshot */ } else throw e; } Prevention
- Keep the Spark runtime version aligned with the version that writes the table metadata
- Avoid mixing Iceberg runtime versions against tables written by newer releases
When it happens
Trigger: Calling RewriteManifestsSparkAction.execute() on a table whose snapshot contains a manifest with a content type other than DATA or DELETES (e.g. written by a newer Iceberg spec with an added content type).
Common situations: Reading tables produced by a newer Iceberg version with an older Spark runtime; corrupted or hand-edited metadata assigning an unexpected content value.
Related errors
- Cannot convert type to SQL: %s
- Unknown manifest content:
- Cannot use column %s of type %s in ZOrdering, the type is un
- Unsupported logical type:
- Unsupported type:
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/d554a0e075d30bef.
Report an issue: GitHub.