apache/druid · error · ForbiddenException
authResult.getErrorMessage()
Error message
authResult.getErrorMessage()
What it means
SupervisorResource's specPost endpoint performs an authorization check (via AuthorizerMapper/AuthConfig) before validating and creating a supervisor spec. If the authResult does not allow access with no restriction, it throws ForbiddenException using the authorization result's error message. This is Druid's standard per-resource action check: the authenticated user lacks a required action (e.g. WRITE on DATASOURCE) for the supplied supervisor spec.
Source
Thrown at indexing-service/src/main/java/org/apache/druid/indexing/overlord/supervisor/SupervisorResource.java:157
catch (UOE e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(
ImmutableMap.of(
"error",
e.getMessage()
)
)
.build();
}
AuthorizationResult authResult = AuthorizationUtils.authorizeAllResourceActions(
req,
resourceActions,
authorizerMapper
);
if (!authResult.allowAccessWithNoRestriction()) {
throw new ForbiddenException(authResult.getErrorMessage());
}
try {
spec.validateSpec();
}
catch (DruidException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(ImmutableMap.of("error", e.getMessage()))
.build();
}
final SupervisorSpecUpdateResult updateResult =
manager.createOrUpdateAndStartSupervisor(spec, Boolean.TRUE.equals(skipRestartIfUnmodified));
if (updateResult.isModified() || updateResult.isRestarted()) {
auditSupervisorUpdate(spec, req);
}
return Response.ok(View on GitHub (pinned to 9b90983fd2)
Solutions
- Grant the user's role a WRITE permission (type DATASOURCE, name = the spec's datasource, or wildcard '.*') in the authorizer JSON in coordinator dynamic config or authorizer config.
- Verify which authenticator/authorizer identity is being used (check the request's authentication result / auth logs) and fix credentials if the wrong identity is resolved.
- Check that the datasource name in the supervisor spec matches the resource patterns in the role; adjust the role or the spec.
- If access should be unrestricted, adjust druid.auth.authorizers / AuthConfig to use an authorizer that allows the request.
Example fix
// before: role has only READ permission
{"name": "myRole", "permissions": [{"resource": {"type": "DATASOURCE", "name": "wiki"}, "action": "READ"}]}
// after: add WRITE so supervisor POST is authorized
{"name": "myRole", "permissions": [{"resource": {"type": "DATASOURCE", "name": "wiki"}, "action": "READ"}, {"resource": {"type": "DATASOURCE", "name": "wiki"}, "action": "WRITE"}]} Defensive patterns
Strategy: try-catch
Validate before calling
// check user permissions before POSTing the supervisor spec
fetch('/druid/indexer/v1/authorizer/test', {method:'POST', body: JSON.stringify({resource:{type:'DATASOURCE',name:spec.spec.dataSchema.dataSource}, action:'WRITE'})}); Try / catch
try { postSupervisor(spec); } catch (WebApplicationException e) { if (e.getResponse().getStatus() == 403) { handleForbidden(e.getResponse().readEntity(String.class)); } else { throw e; } } Prevention
- Grant WRITE on DATASOURCE to roles that manage supervisors
- Verify the identity used for API calls has authorizer roles configured
- Keep the datasource name in the spec aligned with role permission patterns
When it happens
Trigger: POST /druid/indexer/v1/supervisor (specPost) where the authenticated user/role fails the authorization check against the configured authorizer: required action (typically WRITE) on the target datasource resource is denied, or the resource identified in the spec is filtered out by the user's authorizer prefix.
Common situations: Operators calling the supervisor API with a service account whose role lacks write permission on the datasource; using an identity that only has READ; misconfigured druid.auth authenticator/authorizer roles missing the datasource in permissions; Kerberos/LDAP users without the expected group mappings.
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
- User [%s] does not have role [%s].
- Group mapping [%s] already has role [%s].
- Group mapping [%s] does not have role [%s].
- User [%s] does not exist.
- Task type [%s], does not support input source based security
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/6ece419744f2e218.
Report an issue: GitHub.