theonedev/onedev · error · UnauthorizedException
This api can only be accessed via cluster credential
Error message
This api can only be accessed via cluster credential
What it means
ClusterResource.downloadSiteFiles is an internal cluster-only API that streams files from the server's site directory matching a pattern set. It rejects any caller not authenticated as the system principal via the cluster credential, throwing UnauthorizedException "This api can only be accessed via cluster credential".
Source
Thrown at server-core/src/main/java/io/onedev/server/cluster/ClusterResource.java:102
private PackBlobService packBlobService;
@Inject
private BuildService buildService;
@Inject
private RunCacheService cacheService;
@Inject
private WorkExecutionService workExecutionService;
@Path("/site-files")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@GET
public Response downloadSiteFiles(@QueryParam("path") String path,
@QueryParam("patterns") String patterns,
@QueryParam("readLock") String readLock) {
if (!SecurityUtils.isSystem())
throw new UnauthorizedException("This api can only be accessed via cluster credential");
StreamingOutput output = os -> {
Runnable sendFiles = () -> {
File directory = new File(Bootstrap.getSiteDir(), path);
PatternSet patternSet = PatternSet.parse(patterns);
patternSet.getExcludes().add(SHARE_TEST_DIR + "/**");
TarUtils.tar(directory, patternSet.getIncludes(), patternSet.getExcludes(), os, false);
};
if (readLock != null)
read(readLock, sendFiles);
else
sendFiles.run();
};
return ok(output).build();
}
@Path("/site-file")
@Produces(MediaType.APPLICATION_OCTET_STREAM)View on GitHub (pinned to d44925c47c)
Solutions
- Use the cluster credential (server secret) authentication for this endpoint — it is meant for inter-server cluster communication only.
- Verify both member servers share the same cluster secret/token so SecurityUtils.isSystem() evaluates true.
- Do not call this endpoint from user code; use the OneDev UI or public APIs to access site files.
- Check reverse proxy / auth middleware is not stripping the cluster auth header before it reaches OneDev.
Example fix
// before curl -H "Authorization: Bearer <personal-access-token>" \ https://onedev.example.com/api/cluster/site-files?path=cache // after (cluster member using cluster credential setup, not a PAT) // ensure the request originates from an authenticated cluster member; // configure identical cluster secrets on both servers, then call via the // cluster client rather than raw HTTP with user tokens.
Defensive patterns
Strategy: try-catch
Validate before calling
if (!SecurityUtils.isSystem())
throw new IllegalStateException("Cluster endpoint requires cluster credential, not user auth"); Try / catch
try {
return target("cluster/site-files").get(byte[].class);
} catch (ForbiddenException | UnauthorizedException e) {
// not called with cluster credential; fix client authentication
} Prevention
- Never call internal /api/cluster/* endpoints with personal access tokens.
- Keep cluster secrets identical across all member servers.
- Document these endpoints as internal-only for your team.
When it happens
Trigger: Calling GET on the site-files endpoint with normal user credentials, a regular access token, or no credentials instead of the server's cluster secret; pointing a third-party tool at this internal endpoint.
Common situations: Manually curling the endpoint for debugging without cluster auth; a member server whose cluster token is missing/mismatched fails the system check; firewall-routed requests stripping the credential header; API exploration with a regular PAT.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- Authentication required
- Not authenticated
- Invalid or expired access token
- Account is disabled
- Two-factor authentication not enabled
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/780069907addf398.
Report an issue: GitHub.