SonarSource/sonarqube · error · UnauthorizedException
User is not authenticated
Error message
User is not authenticated
What it means
ThreadLocalUserSession.get() is the accessor for the request-scoped UserSession stored in a ThreadLocal. When get() is called before any session has been bound to the current thread (DELEGATE.get() returns null), it throws UnauthorizedException('User is not authenticated'). The server uses this to signal that the current request carries no valid user session.
Source
Thrown at server/sonar-webserver-auth/src/main/java/org/sonar/server/user/ThreadLocalUserSession.java:45
import org.sonar.db.entity.EntityDto;
import org.sonar.db.permission.GlobalPermission;
import org.sonar.db.permission.ProjectPermission;
import org.sonar.db.user.GroupDto;
import org.sonar.server.exceptions.UnauthorizedException;
/**
* Part of the current HTTP session
*/
public class ThreadLocalUserSession implements UserSession {
private static final ThreadLocal<UserSession> DELEGATE = new ThreadLocal<>();
public UserSession get() {
UserSession session = DELEGATE.get();
if (session != null) {
return session;
}
throw new UnauthorizedException("User is not authenticated");
}
public void set(UserSession session) {
DELEGATE.set(session);
}
public void unload() {
DELEGATE.remove();
}
public boolean hasSession() {
return DELEGATE.get() != null;
}
@Override
@CheckForNull
public Long getLastSonarlintConnectionDate() {
return get().getLastSonarlintConnectionDate();View on GitHub (pinned to 184c821202)
Solutions
- Authenticate the request: pass a valid user token ('Authorization: Bearer <token>') or basic credentials to the API call
- Check authentication requirements of the endpoint and use an endpoint that permits anonymous access, or enable anonymous access in server settings if intended
- Verify the token was not revoked/expired and belongs to an active user (Admin > Security > Users)
- In server-side code, ensure UserSession is set via ThreadLocalUserSession.set() before calling accessors
Example fix
// before curl http://sonar.example.org/api/users/current // after curl -u "mytoken:" http://sonar.example.org/api/users/current
Defensive patterns
Strategy: try-catch
Validate before calling
// client: prefer a cheap auth probe before dependent calls
const res = await fetch(`${baseUrl}/api/authentication/validate`, { headers: { Authorization: `Bearer ${token}` } });
if (!res.ok || !(await res.json()).valid) throw new Error('Not authenticated: supply a valid SonarQube user token'); Type guard
// Java server-side guard: if (sessionRef.get() == null /* or catch UnauthorizedException */) redirect/401 before calling getLogin/getUuid
Try / catch
try {
String login = userSession.getLogin();
} catch (UnauthorizedException e) {
// respond 401 / prompt for token
return Response.status(401).build();
} Prevention
- Always send a valid Authorization header (token or basic) for authenticated endpoints
- Check /api/authentication/validate or /api/users/current before long workflows
- Watch for anonymous mode: endpoints requiring identity still need a token
- In server plugins, verify a session exists before using ThreadLocalUserSession accessors
When it happens
Trigger: Calling any accessor (getLogin, getUuid, getName, getGroups, getIdentityProvider, getLastSonarlintConnectionDate) on ThreadLocalUserSession for a request with no authenticated session, e.g. anonymous request to an endpoint requiring authentication, or a missing/invalid credentials header.
Common situations: Scripts or clients calling the SonarQube web API without a token; an expired/revoked token; provisioning or background threads that never set a session before querying user info.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Identity provider %s does not exist or is not enabled
- Authentication is required
- Token doesn't exist
- 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/b6d3e8d83c9bf6d9.
Report an issue: GitHub.