{"record":{"id":"ca8db9f2f99c0277","repo":"theonedev/onedev","slug":"no-package-read-permission-for-project-project-ca8db9","errorCode":null,"errorMessage":"No package read permission for project: ${project.path}","messagePattern":"No package read permission for project: (.+?)","errorType":"exception","errorClass":"UnauthorizedException","httpStatus":null,"severity":"error","filePath":"server-plugin/server-plugin-pack-gem/src/main/java/io/onedev/server/plugin/pack/gem/GemPackHandler.java","lineNumber":497,"sourceCode":"\t}\n\n\t@Override\n\tpublic String getApiKey(HttpServletRequest request) {\n\t\tvar authzHeader = request.getHeader(HttpHeaders.AUTHORIZATION);\n\t\tif (authzHeader != null&& authzHeader.toLowerCase().startsWith(\"bearer \"))\n\t\t\treturn StringUtils.substringAfter(authzHeader, \" \");\n\t\telse\n\t\t\treturn null;\n\t}\n\t\n\tprivate Project checkProject(Long projectId, boolean needsToWrite) {\n\t\tvar project = projectService.load(projectId);\n\t\tif (!project.isPackManagement()) {\n\t\t\tthrow new ClientException(SC_NOT_ACCEPTABLE, \"Package management not enabled for project '\" + project.getPath() + \"'\");\n\t\t} else if (needsToWrite && !SecurityUtils.canWritePack(project)) {\n\t\t\tthrow new UnauthorizedException(\"No package write permission for project: \" + project.getPath());\n\t\t} else if (!needsToWrite && !SecurityUtils.canReadPack(project)) {\n\t\t\tthrow new UnauthorizedException(\"No package read permission for project: \" + project.getPath());\n\t\t}\n\t\treturn project;\n\t}\n\n\tprivate UserMarshal getGemVersion(String version) {\n\t\treturn new UserMarshal(\"Gem::Version\", newArrayList(version));\n\t}\n\t\n\tprivate UserMarshal getGemRequirement(Map<String, UserMarshal> requiredVersions) {\n\t\tvar requirements = new ArrayList<>();\n\t\tfor (var entry: requiredVersions.entrySet()) \n\t\t\trequirements.add(newArrayList(entry.getKey(), entry.getValue()));\n\t\tvar value = new ArrayList<>();\n\t\tvalue.add(requirements);\n\t\treturn new UserMarshal(\"Gem::Requirement\", value);\t\n\t}\n\t\n\tprivate UserMarshal getGemVersion(MappingNode node) {","sourceCodeStart":479,"sourceCodeEnd":515,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-plugin/server-plugin-pack-gem/src/main/java/io/onedev/server/plugin/pack/gem/GemPackHandler.java#L479-L515","documentation":"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.","triggerScenarios":"gem install/fetch/spec request handled by GemPackHandler where the authenticated (or anonymous) user lacks Pack Read permission on the project.","commonSituations":"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.","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."],"exampleFix":"# ~/.gem/credentials\n:onedev: MYTOKEN\n# then\ngem sources -a https://onedev.example.com/~project/gem --config-file ~/.gem/credentials","handlingStrategy":"validation","validationCode":"// confirm credentials are configured for the OneDev gem host before install/fetch\n// ~/.gem/credentials must contain the token for :onedev host\n// test: curl -u user:token https://onedev/~project/gem/api/v1/versions","typeGuard":null,"tryCatchPattern":"try {\n    gemFetch(source, spec);\n} catch (UnauthorizedException e) {\n    if (String(e).contains('read permission')) throw new SecurityException(\"Add Pack Read permission or configure gem credentials\", e);\n    throw e;\n}","preventionTips":["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."],"tags":["package-management","authorization","permissions"],"backgroundTag":"permission-denied","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}