apache/iceberg · error · IllegalArgumentException
Unknown planning mode: ${mode}
Error message
Unknown planning mode: ${mode} What it means
shouldPlanLocally() switches on a configured planning mode (enum of AUTO and remote/local preferences); an unrecognized mode reaches the default branch and throws IllegalArgumentException('Unknown planning mode'). This indicates the stored mode value is not a valid PlanningMode, typically from an invalid property value or a version mismatch where an older core sees a newer mode name.
Source
Thrown at core/src/main/java/org/apache/iceberg/BaseDistributedDataScan.java:256
private boolean shouldPlanLocally(PlanningMode mode, List<ManifestFile> manifests) {
if (context().planWithCustomizedExecutor()) {
return true;
}
switch (mode) {
case LOCAL:
return true;
case DISTRIBUTED:
return manifests.isEmpty();
case AUTO:
return remoteParallelism() <= localParallelism
|| manifests.size() <= 2 * localParallelism
|| totalSize(manifests) <= localPlanningSizeThreshold;
default:
throw new IllegalArgumentException("Unknown planning mode: " + mode);
}
}
private long totalSize(List<ManifestFile> manifests) {
return manifests.stream().mapToLong(ManifestFile::length).sum();
}
private boolean shouldCopyDataFiles(boolean planDataLocally, boolean loadColumnStats) {
return planDataLocally
|| shouldCopyRemotelyPlannedDataFiles()
|| (loadColumnStats && !shouldReturnColumnStats());
}
@SuppressWarnings("unchecked")
private CloseableIterable<ScanTask> planFileTasksLocally(
List<ManifestFile> dataManifests, List<ManifestFile> deleteManifests) {
LOG.info("Planning file tasks locally for table {}", table().name());
ManifestGroup manifestGroup = newManifestGroup(dataManifests, deleteManifests);View on GitHub (pinned to 86d9c8fc54)
Solutions
- Set the planning mode property to one of the valid enum values (auto, and the defined remote/local modes)
- Check for Iceberg version mismatch between the writer of the config and the reader
- Use the enum constant programmatically instead of a raw string where possible
- Validate configuration values at startup before launching scans
Example fix
// before
String mode = conf.get("iceberg.distributed.plan-mode"); // e.g. "automatic"
// after
String mode = conf.get("iceberg.distributed.plan-mode", "auto"); // must be a valid PlanningMode name
Preconditions.checkArgument(mode.equals("auto") || mode.equals("local") || mode.equals("remote"),
"Invalid planning mode: %s", mode); Defensive patterns
Strategy: validation
Validate before calling
String mode = props.get("plan-mode");
Set<String> valid = Set.of("auto", "local", "remote"); // adjust to actual enum names
if (mode != null && !valid.contains(mode)) {
throw new IllegalArgumentException("Invalid planning mode: " + mode);
} Type guard
null
Try / catch
try { planFiles(); } catch (IllegalArgumentException e) { /* fix plan-mode config */ } Prevention
- Copy valid enum values from the Iceberg PlanningMode enum, don't free-type them
- Align Iceberg versions across config producers and consumers
- Validate all scan-related properties at app startup
- Use programmatic enum constants where available
When it happens
Trigger: Setting the distributed-scan planning mode property to a value outside the enum, or deserializing a mode saved by a newer Iceberg version.
Common situations: Typo in configuration property value (e.g. 'autto', 'remote-paralell'); config from a different Iceberg version; programmatic construction with a null/foreign mode object.
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
- Invalid distribution mode: %s
- Invalid file format: %s
- Cannot support given S3 encryption type:
- Unknown catalog type:
- Invalid isolation level: %s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/18f75d9b3bf96c9d.
Report an issue: GitHub.