spring-projects/spring-security · error · UsernameNotFoundException

JdbcDaoImpl.notFound

JdbcDaoImpl.notFound

Error message

Username {0} not found

What it means

JdbcDaoImpl.loadUserByUsername throws UsernameNotFoundException when the configured users-by-username query returns no rows. The message is resolved from the message source key 'JdbcDaoImpl.notFound' with the username substituted, and Spring Security by default hides the real cause (user vs password mismatch) for security reasons.

Source

Thrown at core/src/main/java/org/springframework/security/core/userdetails/jdbc/JdbcDaoImpl.java:189

	protected void addCustomAuthorities(String username, List<GrantedAuthority> authorities) {
	}

	public String getUsersByUsernameQuery() {
		return this.usersByUsernameQuery;
	}

	@Override
	protected void initDao() throws ApplicationContextException {
		Assert.isTrue(this.enableAuthorities || this.enableGroups,
				"Use of either authorities or groups must be enabled");
	}

	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		List<UserDetails> users = loadUsersByUsername(username);
		if (users.isEmpty()) {
			this.logger.debug("Query returned no results for user '" + username + "'");
			throw new UsernameNotFoundException(this.messages.getMessage("JdbcDaoImpl.notFound",
					new Object[] { username }, "Username {0} not found"));
		}
		UserDetails user = users.get(0); // contains no GrantedAuthority[]
		Set<GrantedAuthority> dbAuthsSet = new HashSet<>();
		if (this.enableAuthorities) {
			dbAuthsSet.addAll(loadUserAuthorities(user.getUsername()));
		}
		if (this.enableGroups) {
			dbAuthsSet.addAll(loadGroupAuthorities(user.getUsername()));
		}
		List<GrantedAuthority> dbAuths = new ArrayList<>(dbAuthsSet);
		addCustomAuthorities(user.getUsername(), dbAuths);
		if (dbAuths.isEmpty()) {
			this.logger.debug("User '" + username + "' has no authorities and will be treated as 'not found'");
			throw new UsernameNotFoundException(this.messages.getMessage("JdbcDaoImpl.noAuthority",
					new Object[] { username }, "User {0} has no GrantedAuthority"));
		}
		return createUserDetails(username, user, dbAuths);

View on GitHub (pinned to 96852e8860)

Solutions

  1. Verify the username exists in the DB by running the configured usersByUsernameQuery manually against the same DataSource
  2. Check DataSource configuration (JDBC URL, schema, environment) — a common cause is pointing at an empty or wrong database
  3. Handle case sensitivity: use lower(username)=lower(?) in the query or ensure consistent casing
  4. Seed the user data if this is a fresh deployment

Example fix

// before
usersByUsernameQuery=select username,password,enabled from users where username = ?
// after (case-insensitive)
usersByUsernameQuery=select username,password,enabled from users where lower(username) = lower(?)
Defensive patterns

Strategy: try-catch

Validate before calling

Long count = jdbc.queryForObject(usersByUsernameQuery, Long.class, username); if (count == null || count == 0) { /* user absent — handle before load */ }

Try / catch

try { user = dao.loadUserByUsername(username); } catch (UsernameNotFoundException ex) { throw new BadCredentialsException("Bad credentials"); }

Prevention

When it happens

Trigger: Calling loadUserByUsername with a username that does not exist in the users table, when the usersByUsernameQuery finds no matching rows.

Common situations: Typo in username, wrong case sensitivity with case-sensitive DB collation, querying the wrong database/schema, users table not seeded in a fresh environment, JDBC DataSource pointing at a different environment.

Understand the failure class

Background: "User not found", "Invalid user", and "does not exist": what missing-user lookup errors mean across Rocket.Chat, LiteLLM, Phabricator, rustfs, and pnpm — this error's family across 10 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/e4bd8fb7ecf04a03. Report an issue: GitHub.