theonedev/onedev · error · ValidationException
Specified commit is not reachable from specified ref
Error message
Specified commit is not reachable from specified ref
What it means
runBuild checks with gitService.isMergedInto() that the supplied commitHash is an ancestor of (reachable from) the supplied ref. If the commit is not contained in the ref's history, a ValidationException is thrown (HTTP 400), because a build on that ref would not actually contain the requested commit.
Source
Thrown at server-core/src/main/java/io/onedev/server/rest/resource/JobRunResource.java:85
var subject = SecurityUtils.getSubject();
var user = SecurityUtils.getUser(subject);
if (jobRun instanceof JobRunOnCommit) {
JobRunOnCommit jobRunOnCommit = (JobRunOnCommit) jobRun;
project = projectService.load(jobRunOnCommit.getProjectId());
if (!SecurityUtils.canRunJob(subject, project, jobRun.getJobName()))
throw new UnauthorizedException();
if (!jobRunOnCommit.getRefName().startsWith(Constants.R_REFS))
throw new ValidationException("Ref name should start with " + Constants.R_REFS);
RevCommit refCommit = project.getRevCommit(jobRunOnCommit.getRefName(), true);
commitId = ObjectId.fromString(jobRunOnCommit.getCommitHash());
if (!gitService.isMergedInto(project, null, commitId, refCommit))
throw new ValidationException("Specified commit is not reachable from specified ref");
refName = jobRunOnCommit.getRefName();
request = null;
} else {
JobRunOnPullRequest jobRunOnPullRequest = (JobRunOnPullRequest) jobRun;
request = pullRequestService.load(jobRunOnPullRequest.getPullRequestId());
refName = request.getMergeRef();
project = request.getProject();
if (!SecurityUtils.canRunJob(subject, request.getProject(), jobRun.getJobName()))
throw new UnauthorizedException();
MergePreview preview = request.checkMergePreview();
if (preview == null)
throw new ValidationException("Pull request merge preview not calculated yet");
if (preview.getMergeCommitHash() == null)
throw new ValidationException("Pull request has merge conflicts");
View on GitHub (pinned to d44925c47c)
Solutions
- Verify the commit is an ancestor: git merge-base --is-ancestor <commit> <ref>
- Use the ref that actually contains the commit (e.g. the feature branch ref)
- Re-resolve the commit hash from the current ref tip before submitting
Example fix
// before
{"refName":"refs/heads/main","commitHash":"abc123..."} // commit lives on feature/x
// after
{"refName":"refs/heads/feature/x","commitHash":"abc123..."} Defensive patterns
Strategy: validation
Validate before calling
// locally verify ancestry before submitting
git merge-base --is-ancestor <commitHash> <refName> || fail('commit not reachable from ref'); Try / catch
try { runBuild(req); } catch (WebApplicationException e) { if (msg contains 'not reachable') reResolveCommitAndRef(); else throw e; } Prevention
- Derive commit hash and ref from the same source (e.g. git rev-parse refs/heads/x)
- Avoid hardcoding commit hashes across branches
- Handle force-push invalidation by re-resolving refs
When it happens
Trigger: POSTing a JobRunOnCommit where commitHash points to a commit on another branch, an orphaned commit, or a commit pushed after the ref advanced past it.
Common situations: Passing HEAD of a feature branch while naming the main branch as ref; commit garbage-collected or force-pushed away; copying commit hash from a different repository.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Ref name should start with refs/
- Count should not be greater than ${RestConstants.MAX_PAGE_SI
- Count should not be greater than
- Invalid commit id
- Unexpected query params:
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/2242b4bf8392d608.
Report an issue: GitHub.