theonedev/onedev · error · UnauthorizedException
No package read permission for project
Error message
No package read permission for project: ${project.path} What it means
checkProject throws UnauthorizedException when the request is read-only (needsToWrite=false, e.g. downloading or listing gems) but SecurityUtils.canReadPack(project) is false. The user is not allowed to read packages of the project, so the gem fetch is refused before any blob lookup.
Solutions
- Grant the user/group 'Read Package' (or Write) permission in Project -> Permissions.
- Configure credentials in the gem client for the OneDev gem host (e.g. via :gem_sources entry in ~/.gem/credentials or token in URL).
- If packages should be public, enable anonymous pack read via project/global permissions.
- Check for expired tokens and re-authenticate.
Example fix
# ~/.gem/credentials :onedev: MYTOKEN # then gem sources -a https://onedev.example.com/~project/gem --config-file ~/.gem/credentials
Defensive patterns
Strategy: validation
Validate before calling
// confirm credentials are configured for the OneDev gem host before install/fetch // ~/.gem/credentials must contain the token for :onedev host // test: curl -u user:token https://onedev/~project/gem/api/v1/versions
Try / catch
try {
gemFetch(source, spec);
} catch (UnauthorizedException e) {
if (String(e).contains('read permission')) throw new SecurityException("Add Pack Read permission or configure gem credentials", e);
throw e;
} Prevention
- Store OneDev gem host credentials in ~/.gem/credentials on all dev machines and CI images.
- Track token expiry and rotate proactively.
- Request Pack Read permission when joining a project that ships gems.
When it happens
Trigger: gem install/fetch/spec request handled by GemPackHandler where the authenticated (or anonymous) user lacks Pack Read permission on the project.
Common situations: Private project packages fetched without credentials; gem client on another machine missing the stored token; anonymous access to a project whose packages are restricted; expired/rotated access token still configured in gem sources.
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
- No package write permission for project
- Access denied
- Code read permission is required to import build spec
- Code read permission required for project
- Code read permission required to query pull requests
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/ca8db9f2f99c0277.
Report an issue: GitHub.
Appendix: source
Thrown at server-plugin/server-plugin-pack-gem/src/main/java/io/onedev/server/plugin/pack/gem/GemPackHandler.java:497
}
@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);
}
private UserMarshal getGemVersion(MappingNode node) {View on GitHub (pinned to d44925c47c)