apache/iceberg · error · NotAuthorizedException
Not authorized
Error message
Not authorized: %s
What it means
RESTClient's default error handler maps HTTP 401 responses to NotAuthorizedException. The server rejected the request because authentication failed or credentials were missing/expired. This is the client-side surface of the server's auth check in the Iceberg REST protocol.
Solutions
- Check the catalog properties for authentication (token, credential, oauth2-server-uri) and supply a valid token
- Refresh or re-obtain the OAuth2 bearer token; ensure token refresh is enabled
- Verify the credential (client-id/secret) is still valid with your auth provider
- Inspect the server message for details (e.g. 'invalid token', 'expired credentials')
Example fix
// before
Map<String, String> props = Map.of("uri", "https://catalog.example.com");
// after
Map<String, String> props = Map.of(
"uri", "https://catalog.example.com",
"token", validBearerToken); Defensive patterns
Strategy: try-catch
Validate before calling
if (props.get("token") == null && props.get("credential") == null) {
throw new IllegalArgumentException("Provide 'token' or 'credential' catalog property for auth");
} Try / catch
try {
catalog.loadTable(identifier);
} catch (NotAuthorizedException e) {
refreshTokenAndRebuildCatalog();
} Prevention
- Enable automatic token refresh instead of static long-lived tokens
- Rotate credentials before expiry in long-running jobs
- Verify auth properties at catalog construction time
When it happens
Trigger: HTTP 401 returned by the REST server during any catalog request; e.g. missing Authorization header, expired OAuth2 token, or invalid credentials supplied via AuthConfig/catalog properties.
Common situations: Expired bearer token in a long-running Spark job, missing 'credential' or 'token' catalog property, misconfigured OAuth2 server URL, clock skew invalidating tokens, or rotating secrets without restarting the client.
Related errors
- Not authorized
- Failed to refresh token
- Invalid credential:
- Malformed request
- Not authorized to call the BigQuery API or access this…
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/ff409e2631b53044.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/apache/iceberg/rest/ErrorHandlers.java:343
public ErrorResponse parseResponse(int code, String json) {
try {
return ErrorResponseParser.fromJson(json);
} catch (Exception x) {
LOG.warn("Unable to parse error response", x);
}
return ErrorResponse.builder().responseCode(code).withMessage(json).build();
}
@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 {View on GitHub (pinned to 86d9c8fc54)