{"record":{"id":"8b97b1db53f3cf2d","repo":"apache/druid","slug":"authresult-geterrormessage-8b97b1","errorCode":null,"errorMessage":"authResult.getErrorMessage()","messagePattern":"authResult\\.getErrorMessage\\(\\)","errorType":"http","errorClass":"ForbiddenException","httpStatus":403,"severity":"error","filePath":"indexing-service/src/main/java/org/apache/druid/indexing/overlord/http/security/TaskResourceFilter.java","lineNumber":102,"sourceCode":"                  .entity(StringUtils.format(\"Cannot find any task with id: [%s]\", taskId))\n                  .build()\n      );\n    }\n    final String dataSourceName = Preconditions.checkNotNull(taskOptional.get().getDataSource());\n\n    final ResourceAction resourceAction = new ResourceAction(\n        new Resource(dataSourceName, ResourceType.DATASOURCE),\n        getAction(request)\n    );\n\n    final AuthorizationResult authResult = AuthorizationUtils.authorizeResourceAction(\n        getReq(),\n        resourceAction,\n        getAuthorizerMapper()\n    );\n\n    if (!authResult.allowAccessWithNoRestriction()) {\n      throw new ForbiddenException(authResult.getErrorMessage());\n    }\n\n    return request;\n  }\n}\n","sourceCodeStart":84,"sourceCodeEnd":108,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/indexing-service/src/main/java/org/apache/druid/indexing/overlord/http/security/TaskResourceFilter.java#L84-L108","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Add the denied datasource/task resource actions to the user's role in the authorizer configuration","Inspect the overlord request log for the Access denial message naming the missing resource","Use an account with ADMIN/expanded permissions for state-changing task endpoints","If using basic security, verify the user-role binding actually contains the intended role"],"exampleFix":"// before: role grants READ only, call is POST /task/<id>/shutdown\n// after: add WRITE on the datasource to the role\n// {\"resource\": {\"name\": \"wiki\", \"type\": \"DATASOURCE\"}, \"actions\": [\"READ\", \"WRITE\"]}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { await callTaskApi(taskId, method); } catch (e) { if (e.status === 403) { escalateOrNotify(e.message); } else throw e; }","preventionTips":["Grant WRITE on datasources for accounts that mutate task state","Keep role resources in sync with datasource renames","Verify user-role bindings after auth migrations"],"tags":["http","authorization","security","druid-overlord"],"backgroundTag":"permission-denied","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}