theonedev/onedev · error · IncorrectCredentialsException
Invalid or expired access token
Error message
Invalid or expired access token
What it means
BearerAuthenticationFilter authenticates requests carrying a Bearer token. If the token matches no access token, agent token, or active job context, it throws IncorrectCredentialsException('Invalid or expired access token'), which Shiro treats as failed authentication.
Solutions
- Generate a fresh access token from user profile > Access Tokens and update the client.
- Verify the token belongs to the correct OneDev instance.
- For agents, re-sync the agent token after re-registration.
- Check the Authorization header format is exactly 'Bearer <token>' with no extra whitespace.
Example fix
// before curl -H "Authorization: Bearer old-expired-token" https://onedev/api/projects // after curl -H "Authorization: Bearer <newly-generated-token>" https://onedev/api/projects
Defensive patterns
Strategy: try-catch
Validate before calling
if (bearerToken == null || bearerToken.isBlank()) throw new IllegalArgumentException("Missing bearer token");
// Optionally probe the token against the API before real use Try / catch
try {
// request with Authorization: Bearer <token>
} catch (UnauthenticatedException | IncorrectCredentialsException e) {
// refresh token and retry once
} Prevention
- Rotate and store access tokens securely with expiry tracking
- Re-fetch tokens after revocation, user logout, or job completion
- Verify the 'Bearer ' header prefix and token instance match
When it happens
Trigger: HTTP request with an Authorization: Bearer header whose token is not a valid access token, agent token, or job execution token (e.g. hitting the REST/API endpoint with a stale token).
Common situations: Access token revoked or expired; token rotated in user profile; using an API token from another OneDev instance; agents reinstalled with new tokens; CI job token used after job completion.
Related errors
- Account is disabled
- Authentication required
- Not authenticated
- This api can only be accessed via cluster credential
- Two-factor authentication not enabled
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/7b453dae4dabfeb8.
Report an issue: GitHub.
Appendix: source
Thrown at server-core/src/main/java/io/onedev/server/security/BearerAuthenticationFilter.java:66
Subject subject = SecurityUtils.getSubject();
if (!subject.isAuthenticated()) {
String bearerToken = SecurityUtils.getBearerToken((HttpServletRequest)request);
if (bearerToken != null) {
if (clusterService.getCredential().equals(bearerToken)) {
ThreadContext.bind(userService.getSystem().asSubject());
} else {
var accessToken = accessTokenService.findByValue(bearerToken);
if (accessToken != null) {
ThreadContext.bind(accessToken.asSubject());
} else {
var workspaceContext = workspaceService.getWorkspaceContext(bearerToken, false);
if (workspaceContext != null) {
var workspace = workspaceService.load(workspaceContext.getWorkspaceId());
ThreadContext.bind(workspace.getUser().asSubject());
ProjectEvent.setContextualParticipatingUserIds(workspace.getParticipatingUserIds());
} else if (agentTokenService.find(bearerToken) == null
&& jobService.getJobContext(bearerToken, false) == null) {
throw new IncorrectCredentialsException("Invalid or expired access token");
}
}
}
}
}
return true;
}
@Override
protected void cleanup(ServletRequest request, ServletResponse response, Exception existing)
throws ServletException, IOException {
try {
super.cleanup(request, response, existing);
} finally {
ProjectEvent.clearContextualParticipatingUserIds();
}
}
View on GitHub (pinned to d44925c47c)