apache/iceberg · error · IllegalArgumentException

Unknown manifest content:

Error message

Unknown manifest content: 

What it means

RewriteManifestsSparkAction.loadManifests switches on the snapshot's manifest content type (DATA or DELETES). Any other ManifestContent value falls into the default branch and throws IllegalArgumentException 'Unknown manifest content: '. This is a defensive check for manifest content types the Spark action does not recognize (e.g. a newer spec content type).

Source

Thrown at spark/v3.5/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

  1. Upgrade the Iceberg runtime (iceberg-spark-runtime) on the Spark cluster to a version that supports the manifest content type present in the snapshot.
  2. Pin readers and writers to the same Iceberg version to avoid mixed-version tables.
  3. Rewrite manifests against the table with a newer runtime, or choose a snapshot/rewrite scope that only includes DATA/DELETES manifests.
  4. If seen with a stock release, file a bug with the printed content value — it indicates an unexpected enum.

Example fix

// before
<use iceberg-spark-runtime-3.5_2.13:1.4.0 against tables written by 1.6+ writers>
// after
Upgrade both driver and executors to iceberg-spark-runtime-3.5_2.13 matching the writer version.
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify all snapshots only use known manifest contents before rewriting
boolean knownOnly = Arrays.stream(table.snapshots())
    .allMatch(s -> s.allManifests(table.io()).stream()
        .allMatch(m -> m.content() == ManifestContent.DATA || m.content() == ManifestContent.DELETES));

Try / catch

try {
  rewriteManifests.execute();
} catch (IllegalArgumentException e) {
  if (e.getMessage().startsWith("Unknown manifest content")) {
    throw new IllegalStateException("Runtime too old for this table's manifests; upgrade iceberg-spark-runtime", e);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling rewriteManifests(table) on a table whose snapshot contains manifests with a content type outside {DATA, DELETES} — practically only possible with tables written by a newer Iceberg/engine version introducing a new manifest content type.

Common situations: See trigger scenarios.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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