{"record":{"id":"f1f36b6eabc03225","repo":"apache/dolphinscheduler","slug":"the-user-s-tenant-is-usertenant-have-no-permiss","errorCode":null,"errorMessage":"The user's tenant is ${userTenant} have no permission to access the resource: ${resourceAbsolutePath}","messagePattern":"The user's tenant is (.+?) have no permission to access the resource: (.+?)","errorType":"validation","errorClass":"ServiceException","httpStatus":null,"severity":"error","filePath":"dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/validator/resource/AbstractResourceValidator.java","lineNumber":132,"sourceCode":"\n    public void exceptionUserNoResourcePermission(User user, String resourceAbsolutePath) {\n        if (user.getUserType() == UserType.ADMIN_USER) {\n            return;\n        }\n        // check if the user have resource tenant permission\n        // Parse the resource path to get the tenant code\n        ResourceMetadata resourceMetaData = storageOperator.getResourceMetaData(resourceAbsolutePath);\n\n        if (!resourceAbsolutePath.startsWith(resourceMetaData.getResourceBaseDirectory())) {\n            throw new ServiceException(\"Invalidated resource path: \" + resourceAbsolutePath);\n        }\n\n        // todo: inject the tenant when login\n        Tenant tenant = tenantDao.queryOptionalById(user.getTenantId())\n                .orElseThrow(() -> new ServiceException(Status.TENANT_NOT_EXIST, user.getTenantId()));\n        String userTenant = tenant.getTenantCode();\n        if (!userTenant.equals(resourceMetaData.getTenant())) {\n            throw new ServiceException(\n                    \"The user's tenant is \" + userTenant + \" have no permission to access the resource: \"\n                            + resourceAbsolutePath);\n        }\n    }\n\n}\n","sourceCodeStart":114,"sourceCodeEnd":139,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/validator/resource/AbstractResourceValidator.java#L114-L139","documentation":"exceptionUserNoResourcePermission throws this ServiceException when the tenant code parsed from the resource path does not match the login user's tenant, so the user is not allowed to access another tenant's resources.","triggerScenarios":"A user of tenant A requests read/write/delete on a resource whose absolute path resolves to tenant B (e.g. '/tenantB/resources/job.sh'), via any validated resource API.","commonSituations":"Sharing paths between users of different tenants; an admin changing a user's tenant while old workflows still reference the previous tenant's paths; copying resource URLs between environments/tenants.","solutions":["Use resources belonging to the requesting user's own tenant (path prefix must equal the user's tenantCode).","Ask an administrator to move/copy the resource into your tenant's directory if access is legitimately needed.","If the user's tenant changed recently, re-create resources under the new tenant and update workflow references.","Verify the user's tenant assignment in Security > Tenant Management."],"exampleFix":"// before: accessing another tenant's file\nreadResource(loginUserOfTenantA, \"/tenantB/resources/job.sql\", 0, -1);\n// after\nreadResource(loginUserOfTenantA, \"/tenantA/resources/job.sql\", 0, -1);","handlingStrategy":"try-catch","validationCode":"String tenantFromPath = path.split(\"/\")[1]; if (!tenantFromPath.equals(currentUserTenantCode)) { throw new SecurityException(\"Cross-tenant access denied: \" + path); }","typeGuard":null,"tryCatchPattern":"try { resourceOp(path); } catch (ServiceException e) { if (e.getMessage().contains(\"have no permission to access the resource\")) { /* show access-denied UI, offer to request access */ } else { throw e; } }","preventionTips":["Only operate on resources whose path tenant segment equals the user's tenant.","After tenant changes, migrate resources and update workflow references.","Never share cross-tenant resource URLs between users."],"tags":["resource","tenant","permission","multi-tenancy"],"backgroundTag":"permission-denied","analyzedSha":"02eac45a1b6676e639fcbfb4be2243de5771b05d","analyzedAt":"2026-09-06T17:43:00.555Z","contentChangedAt":"2026-09-06T17:43:00.555Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}