alibaba/nacos · warning · UsernameNotFoundException

User not found

Error message

User %s not found

What it means

Same UsernameNotFoundException contract but from the remote/proxying impl: getUser(username) first checks the local cache, then triggers reload() from the peer, and if still absent throws. Because the remote impl never touches a DB directly, a miss here means the peer server also does not have the user (or the peer was unreachable and reload() logged and swallowed the failure).

Solutions

  1. Verify the user exists on the peer server via /user/list or the DB behind it.
  2. Check server logs for [LOAD-USERS] load failed warnings indicating reload() could not reach the peer.
  3. Confirm the peer address in cluster.conf is correct and reachable.
  4. Map UsernameNotFoundException to a 401/invalid-credentials response at the login boundary.

Example fix

// before
UserDetails ud = userService.loadUserByUsername(username);

// after
try {
    UserDetails ud = userService.loadUserByUsername(username);
} catch (UsernameNotFoundException e) {
    log.warn("user not found via remote impl; peer may be unreachable: {}", username);
    throw new BadCredentialsException("invalid credentials");
}
Defensive patterns

Strategy: try-catch

Validate before calling

// For the remote impl, confirm the peer is reachable and the cache loaded.
if (RemoteServerUtil.getServerAddresses().isEmpty()) {
    log.warn("no peer configured; user lookup will miss");
}
// Trigger a cache reload awareness:
if (userService.getCachedUserMap().isEmpty()) {
    log.warn("user cache empty; remote lookup may be needed");
}

Try / catch

try {
    UserDetails ud = userService.loadUserByUsername(username);
} catch (UsernameNotFoundException e) {
    log.warn("user not found via remote impl (peer may be unreachable): {}", username);
    throw new org.springframework.security.authentication.BadCredentialsException("invalid credentials");
}

Prevention

When it happens

Trigger: Login on a console node proxied to a server where the user does not exist; the user cache is cold and reload() returned a list without that user; reload() itself failed silently (caught in AbstractCachedUserService.reload) so the cache stayed empty.

Common situations: User created on one server but not yet visible to the proxying console node; peer temporarily unreachable during reload; user deleted on the peer after the cache was built.

Related errors


AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14). Data as JSON: /api/errors/7834836f6465211e. Report an issue: GitHub.

Appendix: source

Thrown at plugin-default-impl/nacos-default-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/users/NacosUserServiceRemoteImpl.java:62

 * @author xiweng.yy
 */
public class NacosUserServiceRemoteImpl extends AbstractCachedUserService
    implements NacosUserService {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(NacosUserServiceRemoteImpl.class);
    
    private final NacosRestTemplate nacosRestTemplate;
    
    public NacosUserServiceRemoteImpl() {
        super();
        this.nacosRestTemplate = new DefaultHttpClientFactory(LOGGER).createNacosRestTemplate();
    }
    
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = getUser(username);
        if (null == user) {
            throw new UsernameNotFoundException(String.format("User %s not found", username));
        }
        return new NacosUserDetails(user);
    }
    
    @Override
    public void updateUserPassword(String username, String password) {
        Query query = Query.newInstance().addParam("username", username);
        Map<String, String> body = Map.of("newPassword", password);
        try {
            HttpRestResult<String> result = nacosRestTemplate.putForm(
                buildRemoteUserUrlPath(AuthConstants.USER_PATH),
                RemoteServerUtil.buildServerRemoteHeader(), query, body, String.class);
            RemoteServerUtil.singleCheckResult(result);
        } catch (NacosException e) {
            throw new NacosRuntimeException(e.getErrCode(), e.getErrMsg());
        } catch (Exception unpectedException) {
            throw new NacosRuntimeException(NacosException.SERVER_ERROR,
                unpectedException.getMessage());

View on GitHub (pinned to 9b989acdf1)