apache/druid · error · ForbiddenException

authResult.getErrorMessage()

Error message

authResult.getErrorMessage()

What it means

TaskResourceFilter throws ForbiddenException (HTTP 403) carrying the authorizer's denial message when the caller lacks unrestricted access to the task's resource actions (datasource READ/WRITE plus possibly task-type actions). The filter builds the required ResourceActions for the task and evaluates them with the Authorizer before allowing the request through. The embedded message explains which resource and action was denied.

Source

Thrown at indexing-service/src/main/java/org/apache/druid/indexing/overlord/http/security/TaskResourceFilter.java:102

                  .entity(StringUtils.format("Cannot find any task with id: [%s]", taskId))
                  .build()
      );
    }
    final String dataSourceName = Preconditions.checkNotNull(taskOptional.get().getDataSource());

    final ResourceAction resourceAction = new ResourceAction(
        new Resource(dataSourceName, ResourceType.DATASOURCE),
        getAction(request)
    );

    final AuthorizationResult authResult = AuthorizationUtils.authorizeResourceAction(
        getReq(),
        resourceAction,
        getAuthorizerMapper()
    );

    if (!authResult.allowAccessWithNoRestriction()) {
      throw new ForbiddenException(authResult.getErrorMessage());
    }

    return request;
  }
}

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Add the denied datasource/task resource actions to the user's role in the authorizer configuration
  2. Inspect the overlord request log for the Access denial message naming the missing resource
  3. Use an account with ADMIN/expanded permissions for state-changing task endpoints
  4. If using basic security, verify the user-role binding actually contains the intended role

Example fix

// before: role grants READ only, call is POST /task/<id>/shutdown
// after: add WRITE on the datasource to the role
// {"resource": {"name": "wiki", "type": "DATASOURCE"}, "actions": ["READ", "WRITE"]}
Defensive patterns

Strategy: try-catch

Try / catch

try { await callTaskApi(taskId, method); } catch (e) { if (e.status === 403) { escalateOrNotify(e.message); } else throw e; }

Prevention

When it happens

Trigger: A task API request from a user whose roles do not permit the actions the filter computed for the task (e.g. READ on the task's datasource, or WRITE for state-changing endpoints like shutdown).

Common situations: User role only grants READ but the call mutates task state (POST /shutdown, /optimize); datasource renamed so old role grants no longer match; missing TASK-type resource grants when task-level ACLs are enforced; authentication succeeded but the mapped authorizer has no role for the user.

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


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/8b97b1db53f3cf2d. Report an issue: GitHub.