theonedev/onedev · error · UnauthorizedException

No package write permission for project: ${project.path}

Error message

No package write permission for project: ${project.path}

What it means

checkProject throws UnauthorizedException when the request needs write access (needsToWrite=true, e.g. publishing a gem) but SecurityUtils.canWritePack(project) is false for the current user. This is an authorization failure, not a feature toggle issue (that is error 1231).

Source

Thrown at server-plugin/server-plugin-pack-gem/src/main/java/io/onedev/server/plugin/pack/gem/GemPackHandler.java:495

		}
		return null;
	}

	@Override
	public String getApiKey(HttpServletRequest request) {
		var authzHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
		if (authzHeader != null&& authzHeader.toLowerCase().startsWith("bearer "))
			return StringUtils.substringAfter(authzHeader, " ");
		else
			return null;
	}
	
	private Project checkProject(Long projectId, boolean needsToWrite) {
		var project = projectService.load(projectId);
		if (!project.isPackManagement()) {
			throw new ClientException(SC_NOT_ACCEPTABLE, "Package management not enabled for project '" + project.getPath() + "'");
		} else if (needsToWrite && !SecurityUtils.canWritePack(project)) {
			throw new UnauthorizedException("No package write permission for project: " + project.getPath());
		} else if (!needsToWrite && !SecurityUtils.canReadPack(project)) {
			throw new UnauthorizedException("No package read permission for project: " + project.getPath());
		}
		return project;
	}

	private UserMarshal getGemVersion(String version) {
		return new UserMarshal("Gem::Version", newArrayList(version));
	}
	
	private UserMarshal getGemRequirement(Map<String, UserMarshal> requiredVersions) {
		var requirements = new ArrayList<>();
		for (var entry: requiredVersions.entrySet()) 
			requirements.add(newArrayList(entry.getKey(), entry.getValue()));
		var value = new ArrayList<>();
		value.add(requirements);
		return new UserMarshal("Gem::Requirement", value);	
	}

View on GitHub (pinned to d44925c47c)

Solutions

  1. Ask a project admin to grant your user/group 'Write Package' permission under Project -> Permissions.
  2. If pushing from CI, use a job secret/token from a role with pack write access.
  3. Regenerate the personal access token ensuring package write permission is included.
  4. Verify the publish URL targets the project you actually have write access to.

Example fix

// server side: Project -> Permissions -> role -> enable 'Write Package'
# client side: ensure credentials used by gem push belong to that role
gem push --host https://user:token@onedev.example.com/~project/gem mygem-1.0.0.gem
Defensive patterns

Strategy: validation

Validate before calling

// verify effective permission before publishing
// OneDev UI: Project -> Permissions -> your role has 'Write Package'
// or use the REST API to list project roles for the current user

Try / catch

try {
    gemPush(host, token, gemFile);
} catch (UnauthorizedException e) {
    if (String(e).contains('write permission')) throw new SecurityException("Request Pack Write permission on the project", e);
    throw e;
}

Prevention

When it happens

Trigger: gem push / publish request to GemPackHandler where the authenticated user lacks Pack Write permission on the project: they have read-only or no explicit package role.

Common situations: CI job using a job token without pack write scope; developer account added to project with default read-only access; personal access token missing package permissions; wrong project targeted (one you can read but not write).

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/f7e529c21f9fb01e. Report an issue: GitHub.