apache/iceberg · error · ServiceFailureException
Server error
Error message
Server error: %s: %s
What it means
RESTClient's default error handler maps HTTP 500 responses to ServiceFailureException. The catalog server encountered an unexpected internal error while processing the request; the message includes the server-provided error type and message to aid server-side debugging.
Solutions
- Read the server-provided error type and message; they usually pinpoint the server-side failure
- Retry the request with backoff — many 500s are transient backend issues
- Check server logs and health status of the catalog service
- If reproducible, report to the catalog operator with the request details and error type
Example fix
// before
Table table = catalog.loadTable(identifier); // throws ServiceFailureException on 500
// after
Retry.callerRetry -> use backoff:
try {
Table table = catalog.loadTable(identifier);
} catch (ServiceFailureException e) {
// retry with exponential backoff, or fail over to a replica catalog
} Defensive patterns
Strategy: retry
Try / catch
Tasks.foreach(() -> catalog.loadTable(identifier))
.retry(3)
.exponentialBackoff(100, 60000)
.throwFailureWhenFinished(); Prevention
- Build in retry with backoff for catalog calls
- Monitor catalog server health before large batch operations
- Report reproducible 500s to the catalog operator with error type and message
When it happens
Trigger: HTTP 500 returned by the REST server during any catalog request — server bug, backend store failure (e.g. underlying metadata DB or object store error), or unhandled exception server-side.
Common situations: Catalog backend outage or misconfiguration, server version bug triggered by a specific request shape, resource exhaustion on the server, or corrupted metadata causing server-side NPEs.
Related errors
- Planning failed for plan ID
- Cannot call commit on temporary table operations
- Cannot call refresh on temporary table operations
- Cannot commit due to unexpected exception
- Cannot update namespace
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/4aacfca8338ace65.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/apache/iceberg/rest/ErrorHandlers.java:350
}
@Override
public void accept(ErrorResponse error) {
switch (error.code()) {
case 400:
if (IllegalArgumentException.class.getSimpleName().equals(error.type())) {
throw new IllegalArgumentException(error.message());
}
throw new BadRequestException("Malformed request: %s", error.message());
case 401:
throw new NotAuthorizedException("Not authorized: %s", error.message());
case 403:
throw new ForbiddenException("Forbidden: %s", error.message());
case 405:
case 406:
break;
case 500:
throw new ServiceFailureException("Server error: %s: %s", error.type(), error.message());
case 501:
throw new UnsupportedOperationException(error.message());
case 503:
throw new ServiceUnavailableException("Service unavailable: %s", error.message());
}
throw createRESTException(error);
}
}
private static class OAuthErrorHandler extends ErrorHandler {
private static final ErrorHandler INSTANCE = new OAuthErrorHandler();
@Override
public ErrorResponse parseResponse(int code, String json) {
try {
return OAuthErrorResponseParser.fromJson(code, json);
} catch (Exception x) {View on GitHub (pinned to 86d9c8fc54)