{"record":{"id":"7708d1964478aa66","repo":"iflytek/astron-agent","slug":"user-uid-cannot-be-null","errorCode":null,"errorMessage":"User UID cannot be null","messagePattern":"User UID cannot be null","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"console/backend/commons/src/main/java/com/iflytek/astron/console/commons/data/impl/UserInfoDataServiceImpl.java","lineNumber":160,"sourceCode":"        wrapper.eq(UserInfo::getAccountStatus, accountStatus);\n        return userInfoMapper.selectList(wrapper);\n    }\n\n    @Override\n    public List<UserInfo> findActiveUsers() {\n        LambdaQueryWrapper<UserInfo> wrapper = new LambdaQueryWrapper<>();\n        wrapper.eq(UserInfo::getAccountStatus, 1);\n        return userInfoMapper.selectList(wrapper);\n    }\n\n    @Override\n    public UserInfo createOrGetUser(UserInfo userInfo) {\n        if (userInfo == null) {\n            throw new IllegalArgumentException(\"User information cannot be null\");\n        }\n\n        if (userInfo.getUid() == null) {\n            throw new IllegalArgumentException(\"User UID cannot be null\");\n        }\n\n        // First check: fail fast to avoid unnecessary lock contention\n        Optional<UserInfo> existingUser = findByUid(userInfo.getUid());\n        if (existingUser.isPresent()) {\n            return existingUser.get();\n        }\n\n        String lockKey = \"user:create:uid:\" + userInfo.getUid();\n        RLock lock = redissonClient.getLock(lockKey);\n\n        try {\n            // Attempt to acquire the lock: wait up to 5s, hold up to 10s\n            boolean acquired = lock.tryLock(5, 10, TimeUnit.SECONDS);\n\n            if (!acquired) {\n                throw new IllegalStateException(\"Timed out acquiring distributed lock, please try again later\");\n            }","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/console/backend/commons/src/main/java/com/iflytek/astron/console/commons/data/impl/UserInfoDataServiceImpl.java#L142-L178","documentation":"createOrGetUser validates its input before doing any lookup: a null UserInfo or a UserInfo with null uid throws IllegalArgumentException('User UID cannot be null'). It's a fail-fast guard that prevents downstream lock contention and DB queries with a null key.","triggerScenarios":"Calling createOrGetUser with a UserInfo built without setting uid — e.g. constructing UserInfo from a request/SSO payload where the uid field is absent, or mapping code that drops the uid during conversion.","commonSituations":"Auth/SSO token missing the uid claim; API caller omitting uid in the request body; a mapper (MapStruct/BeanUtils) skipping the uid property due to a name mismatch; upstream service returning a partial user object.","solutions":["Populate userInfo.setUid(...) from the authenticated principal before calling createOrGetUser","Validate the incoming DTO (e.g. @NotNull on uid, or Objects.requireNonNull) at the controller layer","Fix the field mapping if a converter silently drops uid","Return a clear 400 to clients when uid is missing instead of reaching the service"],"exampleFix":"// before\nuserInfoService.createOrGetUser(new UserInfo()); // uid null -> IllegalArgumentException\n// after\nUserInfo u = new UserInfo();\nu.setUid(currentPrincipal.getUid());\nif (u.getUid() == null) throw new BadRequestException(\"uid is required\");\nuserInfoService.createOrGetUser(u);","handlingStrategy":"validation","validationCode":"if (userInfo == null || userInfo.getUid() == null) {\n    throw new ResponseStatusException(HttpStatus.BAD_REQUEST, \"uid is required\");\n}","typeGuard":"// Java: validate before the service call\nboolean hasUid = Optional.ofNullable(userInfo).map(UserInfo::getUid).isPresent();","tryCatchPattern":"try {\n    userInfoService.createOrGetUser(userInfo);\n} catch (IllegalArgumentException e) {\n    log.warn(\"invalid user payload: {}\", e.getMessage());\n    throw new BadRequestException(e.getMessage());\n}","preventionTips":["Annotate DTO uid with @NotNull and validate at the controller","Set uid from the authenticated principal, never from client input alone","Check mapper configs so uid is not silently dropped"],"tags":["java","validation","null","user-management"],"backgroundTag":"null-argument","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}