{"record":{"id":"523413ac5d91c325","repo":"theonedev/onedev","slug":"you-do-not-have-permission-to-pull-from-this-proje","errorCode":null,"errorMessage":"You do not have permission to pull from this project.","messagePattern":"You do not have permission to pull from this project\\.","errorType":"http","errorClass":"UnauthorizedException","httpStatus":401,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/git/GitFilter.java","lineNumber":271,"sourceCode":"\t\tresponse.setHeader(\"Content-Type\", \"application/x-\" + service + \"-advertisement\");\t\t\t\n\t\t\n\t\tPacketLineOut pack = new PacketLineOut(response.getOutputStream());\n\t\tpack.setFlushOnEnd(false);\n\t\tpack.writeString(\"# service=\" + service + \"\\n\");\n\t\tpack.end();\n\t}\n\t\n\tprivate void checkPullPermission(HttpServletRequest request, Project project) {\n\t\tif (!SecurityUtils.canReadCode(project)) {\n\t\t\tboolean isAuthorized = false;\n\t\t\tfor (CodePullAuthorizationSource source: codePullAuthorizationSources) {\n\t\t\t\tif (source.canPullCode(request, project)) {\n\t\t\t\t\tisAuthorized = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!isAuthorized)\n\t\t\t\tthrow new UnauthorizedException(\"You do not have permission to pull from this project.\");\n\t\t}\n\t}\n\n\tprivate void checkPushPermission(HttpServletRequest request, Project project) {\n\t\tif (!SecurityUtils.canWriteCode(project)) \n\t\t\tthrow new UnauthorizedException(\"You do not have permission to push to this project.\");\n\t}\n\n\tprivate boolean canAccessProject(HttpServletRequest request, Project project) {\n\t\tif (!SecurityUtils.canAccessProject(project)) {\n\t\t\tfor (CodePullAuthorizationSource source: codePullAuthorizationSources) {\n\t\t\t\tif (source.canPullCode(request, project)) \n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t} else {\n\t\t\treturn true;\n\t\t}","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/git/GitFilter.java#L253-L289","documentation":"checkPullPermission verifies, after canAccessProject passes, that the requester may pull code from the project — either via SecurityUtils.canReadCode or by matching a registered CodePullAuthorizationSource that authorizes the request. If no path authorizes, it throws this UnauthorizedException. It protects read access to repository data over git HTTP.","triggerScenarios":"processRefs or processPack (fetch/clone) on a project the authenticated user can technically reach but lacks code-read permission on, and no CodePullAuthorizationSource (e.g. pull-request build authorization) grants access via canPullCode.","commonSituations":"CI job clone with a token lacking code-read scope; user added to project without code read role; trying to fetch a dependency repo not covered by your permissions; pull-request authorization source not matching because the request lacks the PR context.","solutions":["Ask a project admin to grant your role the 'Read code' permission","Use an access token created by a user/job with code read permission","If cloning for PR builds, ensure the PR authorization context (job token) is used so canPullCode applies","Verify the clone targets the correct project you actually have access to"],"exampleFix":"// before: job token without code read\ncurl https://onedev.example.com/myproject.git/info/refs?service=git-upload-pack\n\n// after: use a token of a user with 'Read code'\ngit clone https://oauth2:<token-with-read-code>@onedev.example.com/myproject.git","handlingStrategy":"try-catch","validationCode":"// Check role permission via REST before cloning\nconst me = await fetch(`${server}/api/projects/${projectId}/authorizations`);\n// ensure 'Read code' is present for your role","typeGuard":null,"tryCatchPattern":"try {\n  git.clone(url);\n} catch (UnauthorizedException e) {\n  if (e.getMessage().contains(\"permission to pull\")) {\n    requestAccessFromProjectAdmin(project);\n  }\n}","preventionTips":["Verify your role has 'Read code' before scripted clones","Use tokens minted from users with the needed permissions","For PR-based access, clone with the job token that carries PR authorization"],"tags":["git","authorization","permission-denied","onedev"],"backgroundTag":"permission-denied","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}