{"record":{"id":"c403c3b70ea614bc","repo":"theonedev/onedev","slug":"revision-and-path-should-be-specified","errorCode":null,"errorMessage":"Revision and path should be specified","messagePattern":"Revision and path should be specified","errorType":"exception","errorClass":"NotAcceptableException","httpStatus":406,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/web/resource/RawBlobResource.java","lineNumber":81,"sourceCode":"\t\tProject project = getProjectService().findByPath(projectPath);\n\t\tif (project == null)\n\t\t\tthrow new EntityNotFoundException(\"Project not found: \" + projectPath);\n\t\t\n\t\tList<String> revisionAndPathSegments = new ArrayList<>();\n\t\tfor (int i = 0; i < params.getIndexedCount(); i++) {\n\t\t\tString segment = params.get(i).toString();\n\t\t\tif (segment.contains(\"..\"))\n\t\t\t\tthrow new ExplicitException(\"Invalid request path\");\n\t\t\tif (segment.length() != 0)\n\t\t\t\trevisionAndPathSegments.add(segment);\n\t\t}\n\n\t\tBlobIdent blobIdent = new BlobIdent(project, revisionAndPathSegments);\n\n\t\tString revision = blobIdent.revision;\n\t\tString path = blobIdent.path;\n\t\tif (StringUtils.isBlank(revision) || StringUtils.isBlank(path))\n\t\t\tthrow new NotAcceptableException(\"Revision and path should be specified\");\n\n\t\tif (!SecurityUtils.canReadCode(project))\n\t\t\tthrow new UnauthorizedException();\n\n\t\tfinal Blob blob = project.getBlob(new BlobIdent(revision, path, 0), true);\n\n\t\tResourceResponse response = new ResourceResponse();\n\t\tresponse.setAcceptRange(ContentRangeType.BYTES);\n\t\tresponse.getHeaders().addHeader(\"X-Content-Type-Options\", \"nosniff\");\n\t\tresponse.setContentType(MimeUtils.sanitize(project.detectMediaType(blob.getIdent()).toString()));\n\t\t\n\t\tif (blob.getLfsPointer() != null) \n\t\t\tresponse.setContentLength(blob.getLfsPointer().getObjectSize());\n\t\telse \n\t\t\tresponse.setContentLength(blob.getSize());\n\t\t\n\t\tif (!ObjectId.isId(revision))\n\t\t\tresponse.disableCaching();","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/web/resource/RawBlobResource.java#L63-L99","documentation":"After parsing the URL into revision and file path, RawBlobResource requires both to be non-blank; a raw blob request must identify exactly which revision and which file to fetch. A blank revision or path means the URL is malformed for this endpoint.","triggerScenarios":"Raw blob URL missing the revision part or missing the file path, e.g. /~raw/proj/ or /~raw/proj/main/ with no file; empty segments filtered out leaving revisionAndPathSegments with fewer than two entries.","commonSituations":"Trailing-segment loss after URL rewriting/proxies stripping path parts; template-based link generation with an empty file path variable; root path requests against the raw endpoint.","solutions":["Include both a valid revision (branch, tag, or commit hash) and a file path in the URL.","Check reverse proxies/rewrites are not stripping trailing URL segments.","Fix link templates so the file path variable is always populated."],"exampleFix":"// before\nString url = \"/~raw/myproj/main/\"; // missing file path\n// after\nString url = \"/~raw/myproj/main/README.md\";","handlingStrategy":"validation","validationCode":"if (isBlank(revision) || isBlank(path)) throw new IllegalArgumentException(\"Revision and file path are required\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always supply both revision and file path when building raw blob URLs.","Verify proxies don't strip trailing path segments."],"tags":["http","missing-parameter","url"],"backgroundTag":"missing-required-argument","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"}