theonedev/onedev · error · UnauthorizedException
Not authorized to read code of project '${forkedFrom.path}'
Error message
Not authorized to read code of project '${forkedFrom.path}' What it means
createProject throws UnauthorizedException when the request forks from a project (forkedFrom) whose code the subject cannot read. Forking copies build settings from the source project, so read-code access on it is mandatory.
Source
Thrown at server-core/src/main/java/io/onedev/server/rest/resource/ProjectResource.java:299
@POST
public Long createProject(@NotNull @Valid ProjectData data) {
var project = new Project();
data.populate(project, projectService);
var subject = SecurityUtils.getSubject();
var user = SecurityUtils.getUser(subject);
checkProjectCreationPermission(subject, project.getParent());
if (project.getParent() != null && project.isSelfOrAncestorOf(project.getParent()))
throw new NotAcceptableException("Cannot use current or descendant project as parent");
checkProjectNameDuplication(project);
if (project.getForkedFrom() != null) {
var forkedFrom = project.getForkedFrom();
if (!SecurityUtils.canReadCode(subject, forkedFrom))
throw new UnauthorizedException("Not authorized to read code of project '" + forkedFrom.getPath() + "'");
project.getBuildSetting().setBuildPreservations(forkedFrom.getBuildSetting().getBuildPreservations());
project.getBuildSetting().setCachePreserveDays(forkedFrom.getBuildSetting().getCachePreserveDays());
project.getBuildSetting().setJobProperties(forkedFrom.getBuildSetting().getJobProperties());
project.getBuildSetting().setDefaultFixedIssueFilters(forkedFrom.getBuildSetting().getDefaultFixedIssueFilters());
project.getBuildSetting().setListParams(forkedFrom.getBuildSetting().getListParams(false));
project.getBuildSetting().setNamedQueries(forkedFrom.getBuildSetting().getNamedQueries());
project.setPackSetting(forkedFrom.getPackSetting());
project.setPullRequestSetting(forkedFrom.getPullRequestSetting());
project.setWorkspaceSetting(forkedFrom.getWorkspaceSetting());
project.setNamedCommitQueries(forkedFrom.getNamedCommitQueries());
project.setIssueSetting(forkedFrom.getIssueSetting());
project.setNamedCodeCommentQueries(forkedFrom.getNamedCodeCommentQueries());
projectService.create(user, project);
projectService.fork(forkedFrom, project);
} else {
projectService.create(user, project);
}
View on GitHub (pinned to d44925c47c)
Solutions
- Grant the account read-code permission on the fork source project (Project -> Access Control -> Code Read)
- Use a token of a user who can read the source project's code
- Remove forkedFrom if a plain (non-fork) project is intended
- Confirm the forkedFrom path/id refers to the intended project
Example fix
// before
POST /rest/projects {"name":"child","forkedFrom":{"path":"private/lib"}} // no code-read
// after: grant user code-read on private/lib, or drop the field
POST /rest/projects {"name":"child"} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check code-read on fork source
const src = await api.get(`/rest/projects?path=${forkedFromPath}`);
if (!canReadCode(currentUser, src)) throw new Error('no code-read on ' + forkedFromPath); Try / catch
try {
await api.post('/rest/projects', payload);
} catch (e) {
if (e.status === 401 && /read code/.test(e.message)) {
// request code-read grant on the source project or drop forkedFrom
} else throw e;
} Prevention
- Verify fork source accessibility with the same credentials before forking
- Grant automation accounts code-read on all fork sources
- Keep forkedFrom references updated when projects are renamed/moved
- Drop forkedFrom when a plain project is intended
When it happens
Trigger: POST /rest/projects with forkedFrom pointing at project '<path>' where SecurityUtils.canReadCode(subject, forkedFrom) is false — non-member, guest-only, or code-read permission not granted.
Common situations: Forking a private/team project using a personal token of a non-member; automation configured with a forkedFrom id from a different owner's project; group code-read permission removed after the automation was set up.
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 permission to access issue: ${referenceString}
- No permission to write code in issue project
- No permission to read code of target project:
- Code write permission is required to edit auto merge
- Not authorized
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/e2edbf9a28de53e6.
Report an issue: GitHub.