{"record":{"id":"19bc97bdc69570a5","repo":"theonedev/onedev","slug":"ref-name-should-start-with-refs","errorCode":null,"errorMessage":"Ref name should start with refs/","messagePattern":"Ref name should start with refs/","errorType":"http","errorClass":"ValidationException","httpStatus":400,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/rest/resource/JobRunResource.java","lineNumber":78,"sourceCode":"\t@Api(order=100)\n    @POST\n    public Long runBuild(@NotNull @Valid JobRun jobRun) {\n\t\tProject project;\n\t\tString refName;\n\t\tPullRequest request;\n\t\tObjectId commitId;\n\t\t\n\t\tvar subject = SecurityUtils.getSubject();\n\t\tvar user = SecurityUtils.getUser(subject);\n\t\tif (jobRun instanceof JobRunOnCommit) {\n\t\t\tJobRunOnCommit jobRunOnCommit = (JobRunOnCommit) jobRun;\n\t\t\t\n\t    \tproject = projectService.load(jobRunOnCommit.getProjectId());\n\t\t\tif (!SecurityUtils.canRunJob(subject, project, jobRun.getJobName()))\t\t\n\t\t\t\tthrow new UnauthorizedException();\n\n\t\t\tif (!jobRunOnCommit.getRefName().startsWith(Constants.R_REFS)) \n\t\t\t\tthrow new ValidationException(\"Ref name should start with \" + Constants.R_REFS);\n\t\t\t\n\t\t\tRevCommit refCommit = project.getRevCommit(jobRunOnCommit.getRefName(), true);\n\t\t\t\n\t\t\tcommitId = ObjectId.fromString(jobRunOnCommit.getCommitHash());\n\t\t\t\n\t\t\tif (!gitService.isMergedInto(project, null, commitId, refCommit)) \n\t\t\t\tthrow new ValidationException(\"Specified commit is not reachable from specified ref\");\n\t\t\t\n\t\t\trefName = jobRunOnCommit.getRefName();\n\t\t\trequest = null;\n\t\t} else {\n\t\t\tJobRunOnPullRequest jobRunOnPullRequest = (JobRunOnPullRequest) jobRun;\n\t\t\trequest = pullRequestService.load(jobRunOnPullRequest.getPullRequestId());\n\t\t\trefName = request.getMergeRef();\n\t\t\tproject = request.getProject();\n\t\t\t\n\t\t\tif (!SecurityUtils.canRunJob(subject, request.getProject(), jobRun.getJobName()))\t\t\n\t\t\t\tthrow new UnauthorizedException();","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/rest/resource/JobRunResource.java#L60-L96","documentation":"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).","triggerScenarios":"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\".","commonSituations":"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.","solutions":["Prefix the branch with refs/heads/ (e.g. refs/heads/master)","Prefix tags with refs/tags/ (e.g. refs/tags/v1.0)","Normalize ref names in client code before calling the endpoint"],"exampleFix":"// before\n{\"refName\": \"master\", ...}\n// after\n{\"refName\": \"refs/heads/master\", ...}","handlingStrategy":"validation","validationCode":"function toFullRef(name){\n  if (name.startsWith('refs/')) return name;\n  return 'refs/heads/' + name; // or refs/tags/ as appropriate\n}","typeGuard":null,"tryCatchPattern":"try { runBuild(req); } catch (WebApplicationException e) { if (msg contains 'should start with refs/') fixRefNameAndRetry(); else throw e; }","preventionTips":["Always use fully qualified refs (refs/heads/..., refs/tags/...)","Normalize short names at the client boundary","Unit-test ref-name construction in CI scripts"],"tags":["rest","git","validation","refname"],"backgroundTag":"invalid-argument-format","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"}