apache/druid · error · ForbiddenException
<authResult.getErrorMessage()>
Error message
<authResult.getErrorMessage()>
What it means
AuthorizationUtils.verifyUnrestrictedAccessToDatasource throws ForbiddenException when the authenticated user is authorized to access a datasource only with restrictions (policies/row filters), not with unrestricted access. Druid throws it because some HTTP resources require full, unfiltered access to a datasource before serving data. The message carries the authorizer-supplied error text explaining why access was restricted or denied.
Source
Thrown at server/src/main/java/org/apache/druid/server/security/AuthorizationUtils.java:132
AuthorizerMapper authorizerMapper
)
{
ResourceAction resourceAction = createDatasourceResourceAction(datasource, req);
AuthorizationResult authResult = authorizeResourceAction(req, resourceAction, authorizerMapper);
if (!authResult.allowAccessWithNoRestriction()) {
if (authResult.allowBasicAccess()) {
// Basic access was granted, but access was restricted by a policy.
// This is checked to avoid double emitting the forbidden metric if the basic access was denied,
// since the authorizeResourceAction method already emits the metric in that case.
emitAuthMetric(
authorizerMapper.getServiceEmitter(),
authenticationResultFromRequest(req),
resourceAction,
METRIC_FORBIDDEN,
authResult.getErrorMessage()
);
}
throw new ForbiddenException(authResult.getErrorMessage());
}
}
/**
* Returns the authentication information for a request.
*
* @param request http request
* @return authentication result
* @throws IllegalStateException if the request was not authenticated
*/
public static AuthenticationResult authenticationResultFromRequest(final HttpServletRequest request)
{
final AuthenticationResult authenticationResult = (AuthenticationResult) request.getAttribute(
AuthConfig.DRUID_AUTHENTICATION_RESULT
);
if (authenticationResult == null) {
throw new ISE("Null authentication result");View on GitHub (pinned to 9b90983fd2)
Solutions
- Grant the user's role unrestricted READ (and required action) permissions on the datasource in the authorizer configuration.
- Remove or relax row-level policies that restrict the datasource for this user.
- Verify the correct authenticator/authorizer chain is configured so the user maps to the intended roles.
- If the operation legitimately should be restricted, use an API that supports filtered access instead.
Example fix
// before: user has row-filtered READ only -> 403 ForbiddenException
// after: in authorizer config, grant full datasource permission
// authorizer:
// roles:
// datasourceReader:
// permissions:
// - resource: {name: "wikipedia", type: "DATASOURCE"}
// action: READ
// - resource: {name: ".*", type: "DATASOURCE"}
// action: READ
// users: ["alice"] Defensive patterns
Strategy: try-catch
Validate before calling
final Access access = AuthorizationUtils.authorizeResourceAction(req, resourceAction, authorizerMapper);
if (!access.isAllow()) { /* skip call or request higher privilege */ } Type guard
if (authorizerMapper == null || authorizerMapper.getAuthorizer(authResult.getAuthorizerName()) == null) { /* misconfigured authorizer; fix config before calling */ } Try / catch
try { AuthorizationUtils.verifyUnrestrictedAccessToDatasource(req, datasource, authorizerMapper); }
catch (ForbiddenException e) { log.warn("Unrestricted access denied for datasource %s: %s", datasource, e.getMessage()); }
Prevention
- Grant unrestricted READ permissions for datasources used by full-access endpoints.
- Keep authorizer role mappings in version control and review them on user onboarding.
- Test new roles against the endpoints they will call before rollout.
When it happens
Trigger: Calling an endpoint that routes through verifyUnrestrictedAccessToDatasource (e.g. datasource metadata/lookup HTTP resources) while the user's authorizer grants basic access but applies a policy, or denies access entirely.
Common situations: Users granted READ with row-level filters attempting to use endpoints that require full table access; overly restrictive role definitions in the authorizer config; newly created users lacking an authorization role.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- authResult.getErrorMessage()
- authResult.getErrorMessage()
- authResult.getErrorMessage()
- Unauthorized
- Access-Check-Result: %s
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/44ab48da67d86c94.
Report an issue: GitHub.