apache/iceberg · error · IllegalStateException
Remote scan planning cancelled for planId
Error message
Remote scan planning cancelled for planId: %s
What it means
Thrown when the polled remote scan planning result has planStatus=CANCELLED, meaning the scan plan was cancelled on the server (explicit cancel or server-side timeout/cleanup). The client must restart planning.
Solutions
- Retry the whole scan (planTableScan) to create a fresh planId
- Increase server-side planning deadline if plans are timing out server-side
- Check server logs for why the plan was cancelled
- Avoid cancelling by ensuring the client process waits rather than aborting mid-plan
Defensive patterns
Strategy: retry
Try / catch
try { scan.planFiles(); } catch (IllegalStateException e) {
if (e.getMessage().contains("cancelled")) { /* recreate scan and retry */ }
else throw e;
} Prevention
- Don't cancel/close scans mid-planning on the client side
- Set generous server-side planning deadlines
- Retry idempotently — each attempt creates a fresh planId
When it happens
Trigger: fetchPlanningResult polls after the plan was submitted and the server responds CANCELLED for that planId.
Common situations: Server cancels plans exceeding its internal deadline; an operator or client cancelled the plan; server restarts losing plan state and reporting cancelled.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- failureMessage(id, response.errorResponse())
- failureMessage(planId, response.errorResponse())
- Remote scan planning for planId
- Invalid planStatus: for planId
- Cannot assume role to sign REST requests because is not…
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/fd3097da8a830869.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/apache/iceberg/rest/RESTTableScan.java:293
FetchPlanningResultResponse response =
client.get(
resourcePaths.plan(tableIdentifier, id),
headers,
FetchPlanningResultResponse.class,
headers,
ErrorHandlers.planErrorHandler(),
parserContext);
switch (response.planStatus()) {
case COMPLETED:
result.set(response);
break;
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,View on GitHub (pinned to 86d9c8fc54)