YunaiV/yudao-cloud · error · NullPointerException

LoginUser(%d) Table(%s/%s) 未返回数据权限

Error message

LoginUser(%d) Table(%s/%s) 未返回数据权限

What it means

The dept data-permission rule asks the permission service for a DeptDataPermissionRespDTO (cached on the LoginUser context). The RPC contract expects a non-null DTO; if getCheckedData() returns null, the rule deliberately throws NullPointerException with the userId and table in the message, because continuing would silently mean 'no restriction'.

Source

Thrown at yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRule.java:107

    public Expression getExpression(String tableName, Alias tableAlias) {
        // 只有有登陆用户的情况下,才进行数据权限的处理
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        if (loginUser == null) {
            return null;
        }
        // 只有管理员类型的用户,才进行数据权限的处理
        if (ObjectUtil.notEqual(loginUser.getUserType(), UserTypeEnum.ADMIN.getValue())) {
            return null;
        }

        // 获得数据权限
        DeptDataPermissionRespDTO deptDataPermission = loginUser.getContext(CONTEXT_KEY, DeptDataPermissionRespDTO.class);
        // 从上下文中拿不到,则调用逻辑进行获取
        if (deptDataPermission == null) {
            deptDataPermission = permissionApi.getDeptDataPermission(loginUser.getId()).getCheckedData();
            if (deptDataPermission == null) {
                log.error("[getExpression][LoginUser({}) 获取数据权限为 null]", JsonUtils.toJsonString(loginUser));
                throw new NullPointerException(String.format("LoginUser(%d) Table(%s/%s) 未返回数据权限",
                        loginUser.getId(), tableName, tableAlias.getName()));
            }
            // 添加到上下文中,避免重复计算
            loginUser.setContext(CONTEXT_KEY, deptDataPermission);
        }

        // 情况一,如果是 ALL 可查看全部,则无需拼接条件
        if (deptDataPermission.getAll()) {
            return null;
        }

        // 情况二,即不能查看部门,又不能查看自己,则说明 100% 无权限
        if (CollUtil.isEmpty(deptDataPermission.getDeptIds())
            && Boolean.FALSE.equals(deptDataPermission.getSelf())) {
            return new EqualsTo(null, null); // WHERE null = null,可以保证返回的数据为空
        }

        // 情况三,拼接 Dept 和 User 的条件,最后组合

View on GitHub (pinned to 477be9dd49)

Solutions

  1. Make the remote service always return a non-null DeptDataPermissionRespDTO (default: all=false, dept ids empty) when no rules match.
  2. Check the permission service logs for the exact userId at failure time.
  3. Verify both services run compatible framework versions of the permission API.
  4. If null is legitimately possible in your domain, override the rule to treat null as ALL (or none) explicitly instead of relying on the NPE.

Example fix

// before (permission service)
if (CollUtil.isEmpty(rules)) return success(null); // -> NPE in rule

// after
if (CollUtil.isEmpty(rules)) {
    DeptDataPermissionRespDTO dto = new DeptDataPermissionRespDTO();
    dto.setAll(false); dto.setDeptIds(Collections.emptySet()); dto.setSelfIds(Collections.emptySet());
    return success(dto);
}
Defensive patterns

Strategy: try-catch

Validate before calling

DeptDataPermissionRespDTO dto = loginUser.getContext(CONTEXT_KEY, DeptDataPermissionRespDTO.class);
if (dto == null) {
    CommonResult<DeptDataPermissionRespDTO> r = permissionApi.getDeptDataPermission(userId);
    dto = r.isSuccess() ? r.getData() : null;
    if (dto == null) { /* treat as no-permission or all — your policy */ }

Try / catch

try {
    expression = rule.getExpression(tableName, tableAlias, user);
} catch (NullPointerException e) {
    if (e.getMessage() != null && e.getMessage().contains("未返回数据权限")) {
        log.error("permission service returned null for user {}; failing closed", user.getId());
    }
    throw e;
}

Prevention

When it happens

Trigger: system_permission.getDeptDataPermission(userId) returns CommonResult with data=null (success:true but empty body) — e.g. the permission service has no rule rows for the user and returns null instead of a defaulted DTO, or a service refactor started returning null for admins.

Common situations: Partial deployment where the permission service is older/newer than the framework expectation; the user belongs to a tenant with no data-permission configuration and the service treats 'no config' as null; RPC deserialization producing null data on error-swallowing handlers.

Related errors


AI-assisted analysis of YunaiV/yudao-cloud@477be9dd49 (2026-08-14). Data as JSON: /api/errors/a72fc3ec3b714fa5. Report an issue: GitHub.