apache/iceberg · error · RemotePlanTimeoutException
Remote scan planning for planId
Error message
Remote scan planning for planId: %s did not complete within configured limits (timeout=%d ms, maxRetries=%d)
What it means
Thrown as RemotePlanTimeoutException when the submitted remote scan plan never reached a terminal COMPLETED/FAILED/CANCELLED state within the configured polling limits (timeout and max retries). The client stops polling and reports the planId for follow-up.
Solutions
- Increase client wait properties (scan planning timeout ms and max retries) so polling covers server planning duration
- Reduce scan scope (partition filters) so server planning finishes faster
- Scale/optimize the server's planning service
- Use the reported planId to check server state; fetch the plan result out-of-band if the API allows
Example fix
// before
catalog.properties: rest.client.timeout=30000
// after
conf.put("rest.scan.plan.timeout-ms", "300000");
conf.put("rest.scan.plan.max-retries", "20"); Defensive patterns
Strategy: retry
Validate before calling
// ensure client wait budget exceeds expected planning time
long timeoutMs = Long.parseLong(conf.getOrDefault("rest.scan.plan.timeout-ms", "30000"));
int maxRetries = Integer.parseInt(conf.getOrDefault("rest.scan.plan.max-retries", "10")); Try / catch
try { scan.planFiles(); } catch (RemotePlanTimeoutException e) {
// e carries planId; optionally re-fetch or re-plan with bigger budget
} Prevention
- Size timeout/max-retries to cover worst-case server planning duration
- Prune scans with partition/filter predicates to shorten server planning
- Alert on slow planning service latency
When it happens
Trigger: fetchPlanningResult exhausts its Tasks retry loop (maxRetries attempts each waiting up to timeout bounds) while the server keeps returning planStatus SUBMITTED.
Common situations: Very large scans where server planning exceeds client wait time; slow/overloaded REST planning service; client timeout properties set too low (e.g. rest.scan.plan.timeout-ms, max-retries).
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- failureMessage(id, response.errorResponse())
- failureMessage(planId, response.errorResponse())
- Remote scan planning cancelled for planId
- Invalid planStatus: for planId
- Planning failed for plan ID
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/de2661cb1d47dfa8.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/apache/iceberg/rest/RESTTableScan.java:306
case SUBMITTED:
throw new NotCompleteException();
case FAILED:
throw new IllegalStateException(failureMessage(id, response.errorResponse()));
case CANCELLED:
throw new IllegalStateException(
String.format(
Locale.ROOT, "Remote scan planning cancelled for planId: %s", id));
default:
throw new IllegalStateException(
String.format(
Locale.ROOT,
"Invalid planStatus: %s for planId: %s",
response.planStatus(),
id));
}
});
} catch (NotCompleteException e) {
throw new RemotePlanTimeoutException(
String.format(
Locale.ROOT,
"Remote scan planning for planId: %s did not complete within configured limits"
+ " (timeout=%d ms, maxRetries=%d)",
planId,
maxWaitTimeMs,
MAX_RETRIES),
e);
}
FetchPlanningResultResponse response = result.get();
this.scanFileIO =
!response.credentials().isEmpty() ? scanFileIO(response.credentials()) : table().io();
return scanTasksIterable(response.planTasks(), response.fileScanTasks());
}
View on GitHub (pinned to 86d9c8fc54)