apache/iceberg · error · IllegalStateException
failureMessage(id, response.errorResponse())
Error message
failureMessage(id, response.errorResponse())
What it means
Thrown while polling for a submitted remote scan plan (fetchPlanningResult) when the server reports planStatus=FAILED. The server-side planning job completed with an error; the server's errorResponse is included via failureMessage.
Solutions
- Inspect the server errorResponse text in the exception for the root cause
- Check REST server logs for the planId
- Retry the scan or reduce its scope (prune partitions/filters)
- Disable remote planning to plan client-side if the server is unreliable
Defensive patterns
Strategy: try-catch
Try / catch
try { scan.planFiles(); } catch (IllegalStateException e) {
if (e.getMessage().contains("Remote scan planning failed")) {
// retry with client-side planning
} else throw e;
} Prevention
- Keep scans scoped with filters to reduce server-side planning failures
- Ensure the planning service can read the table's metadata and data files
- Monitor server logs and alert on failed planIds
When it happens
Trigger: A scan was SUBMITTED and the polling loop (Tasks retry) then fetched a result with planStatus FAILED; IllegalStateException propagates out of planTableScan/planFiles.
Common situations: Long-running or large scans whose server-side planning job fails midway; server errors like failed manifest reads, expired snapshot, or resource exhaustion during async planning.
Related errors
- failureMessage(planId, response.errorResponse())
- Remote scan planning cancelled for planId
- 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/ebbb8884a7024909.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/apache/iceberg/rest/RESTTableScan.java:291
.run(
id -> {
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"View on GitHub (pinned to 86d9c8fc54)