theonedev/onedev · error · UnauthorizedException

Unauthorized

Error message

Unauthorized

What it means

After the build is found, BuildLogResource enforces SecurityUtils.canAccessLog(build); users who can see the project but not its build logs (e.g. restricted roles) get UnauthorizedException, surfaced as HTTP 401/403 with message "Unauthorized".

Source

Thrown at server-core/src/main/java/io/onedev/server/web/resource/BuildLogResource.java:66

		PageParameters params = attributes.getParameters();

		Long projectId = params.get(PARAM_PROJECT).toLong();
		Long buildNumber = params.get(PARAM_BUILD).toOptionalLong();
		if (buildNumber == null)
			throw new IllegalArgumentException("build number has to be specified");

		if (!SecurityUtils.isSystem()) {
			Project project = getProjectService().load(projectId);			
			Build build = getBuildService().find(project, buildNumber);

			if (build == null) {
				String message = String.format("Unable to find build (project: %s, build number: %d)", 
						project.getPath(), buildNumber);
				throw new EntityNotFoundException(message);
			}
			
			if (!SecurityUtils.canAccessLog(build))
				throw new UnauthorizedException();
		}
		
		ResourceResponse response = new ResourceResponse();
		response.setContentType(MimeTypes.OCTET_STREAM);
		
		response.disableCaching();
		
		try {
			response.setFileName(URLEncoder.encode("build-log.txt", StandardCharsets.UTF_8.name()));
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
		response.setWriteCallback(new WriteCallback() {

			@Override
			public void writeData(Attributes attributes) throws IOException {
				String activeServer = getProjectService().getActiveServer(projectId, true);
				var clusterService = getClusterService();

View on GitHub (pinned to d44925c47c)

Solutions

  1. Request/grant the role that includes access to build logs for the project (Project > Access Control).
  2. Log in with an authorized account instead of anonymous access.
  3. For CI scripts, use an access token whose role permits log access.

Example fix

// before: guest token fetching logs -> 401
curl -H "Authorization: Bearer $GUEST_TOKEN" .../buildlogs?project=1&build=42
// after: token role includes log access
curl -H "Authorization: Bearer $CI_TOKEN" .../buildlogs?project=1&build=42
Defensive patterns

Strategy: try-catch

Validate before calling

// confirm the caller's role grants log access before attempting
canAccessLog = userRoles.some(r => r.project === projectId && r.permissions.includes('VIEW_BUILD_LOGS'));

Try / catch

try { downloadLog(url); } catch (HttpException e) { if (e.getStatusCode() === 403) { requestLogAccess(project); } else throw e; }

Prevention

When it happens

Trigger: GET /~resource/buildlogs?project=..&build=.. with an existing build while the authenticated user (or anonymous) lacks log access permission on that build/project.

Common situations: Guest users opening direct log links shared by developers; service accounts whose role allows running pipelines but not viewing logs; permission model changes removing 'View build logs' from a role.

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


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/a92f06dfbf7ed3f4. Report an issue: GitHub.