theonedev/onedev · error · ValidationException

Ref name should start with refs/

Error message

Ref name should start with refs/

What it means

JobRunResource.runBuild validates that jobRunOnCommit.getRefName() starts with Constants.R_REFS ("refs/"). A ref name lacking this prefix is rejected with a ValidationException (HTTP 400) before any git operation. Git refs in OneDev are always fully qualified (e.g. refs/heads/master, refs/tags/v1.0).

Source

Thrown at server-core/src/main/java/io/onedev/server/rest/resource/JobRunResource.java:78

	@Api(order=100)
    @POST
    public Long runBuild(@NotNull @Valid JobRun jobRun) {
		Project project;
		String refName;
		PullRequest request;
		ObjectId commitId;
		
		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();

View on GitHub (pinned to d44925c47c)

Solutions

  1. Prefix the branch with refs/heads/ (e.g. refs/heads/master)
  2. Prefix tags with refs/tags/ (e.g. refs/tags/v1.0)
  3. Normalize ref names in client code before calling the endpoint

Example fix

// before
{"refName": "master", ...}
// after
{"refName": "refs/heads/master", ...}
Defensive patterns

Strategy: validation

Validate before calling

function toFullRef(name){
  if (name.startsWith('refs/')) return name;
  return 'refs/heads/' + name; // or refs/tags/ as appropriate
}

Try / catch

try { runBuild(req); } catch (WebApplicationException e) { if (msg contains 'should start with refs/') fixRefNameAndRetry(); else throw e; }

Prevention

When it happens

Trigger: Calling POST /job-runs (run build via REST) with a refName like "master", "main", or "v1.0" instead of "refs/heads/master" or "refs/tags/v1.0".

Common situations: Scripts passing short branch names from CI variables; users copying the branch dropdown label instead of the full ref; API clients built against other CI systems that accept short names.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/19bc97bdc69570a5. Report an issue: GitHub.