SonarSource/sonarqube · error · NotFoundException
Token doesn't exist
Error message
Token doesn't exist
What it means
UserTokenAuthentication.authenticate(token) looks up the supplied token in the database. If getUserToken returns null, meaning no row matches the presented token, it throws NotFoundException('Token doesn't exist') so the request fails as unauthenticated with a resource-not-found style error.
Source
Thrown at server/sonar-webserver-auth/src/main/java/org/sonar/server/usertoken/UserTokenAuthentication.java:120
throw AuthenticationException.newBuilder()
.setSource(AuthenticationEvent.Source.local(AuthenticationEvent.Method.SONARQUBE_TOKEN))
.setMessage("User doesn't exist")
.build();
}
request.setAttribute(ACCESS_LOG_TOKEN_NAME, userToken.getName());
return new UserAuthResult(userDto, userToken, UserAuthResult.AuthType.TOKEN);
} catch (NotFoundException | IllegalStateException exception) {
throw AuthenticationException.newBuilder()
.setSource(AuthenticationEvent.Source.local(AuthenticationEvent.Method.SONARQUBE_TOKEN))
.setMessage(exception.getMessage())
.build();
}
}
private UserTokenDto authenticate(String token) {
UserTokenDto userToken = getUserToken(token);
if (userToken == null) {
throw new NotFoundException("Token doesn't exist");
}
if (userToken.isExpired()) {
throw new IllegalStateException("The token expired on " + formatDateTime(userToken.getExpirationDate()));
}
userLastConnectionDatesUpdater.updateLastConnectionDateIfNeeded(userToken);
return userToken;
}
@Nullable
public UserTokenDto getUserToken(String token) {
try (DbSession dbSession = dbClient.openSession(false)) {
return dbClient.userTokenDao().selectByTokenHash(dbSession, tokenGenerator.hash(token));
}
}
}
View on GitHub (pinned to 184c821202)
Solutions
- Generate a new token in SonarQube (My Account > Security) and update the credential store/pipeline secret
- Check the token wasn't deleted or the user deactivated (Admin > Security > Users/Token list)
- Verify you are calling the correct SonarQube instance the token was issued for
- Trim accidental whitespace/newlines when injecting the token from env vars
Example fix
// before
curl -H "Authorization: Bearer ${SONAR_TOKEN_OLD}" http://sonar/api/... # token deleted
// after
curl -H "Authorization: Bearer ${SONAR_TOKEN_NEW}" http://sonar/api/... Defensive patterns
Strategy: try-catch
Validate before calling
// guard before use: non-empty token and correct instance
if (token == null || token.isBlank()) throw new IllegalArgumentException('SONAR_TOKEN is empty or missing'); Type guard
null
Try / catch
try {
await sonarRequest(token);
} catch (err) {
if (err.response?.status === 404) {
// token not found: regenerate and update secret store
} else throw err;
} Prevention
- Store tokens in a secret manager and sync them to all SonarQube instances used
- Track token deletions/revocations (audit logs) against CI consumers
- Never copy-paste tokens across staging/production without regenerating
- Document token ownership so pipelines can be updated on rotation
When it happens
Trigger: An HTTP request authenticated with a user token value that does not exist in the sonar_user_token table — typically a mistyped, revoked, deleted, or fabricated token, or a token from a different SonarQube instance.
Common situations: Rotating tokens in CI (old token deleted while pipeline still references it); copying tokens between environments (staging vs production); typos or whitespace in stored secrets.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- Identity provider %s does not exist or is not enabled
- Authentication is required
- User is not authenticated
- The token expired on
- You're not authorized to push analysis results to the SonarQ
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/960b2632feab1a71.
Report an issue: GitHub.