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
- Make the remote service always return a non-null DeptDataPermissionRespDTO (default: all=false, dept ids empty) when no rules match.
- Check the permission service logs for the exact userId at failure time.
- Verify both services run compatible framework versions of the permission API.
- 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
- Contract-test the permission service: getDeptDataPermission must never return success(null)
- Return a defaulted DTO (all=false, empty sets) instead of null when no rules exist
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.