{"record":{"id":"791d53934d327981","repo":"theonedev/onedev","slug":"unable-to-find-blob-path-path-in-revision-re","errorCode":null,"errorMessage":"Unable to find blob path '<path>' in revision '<revision>'","messagePattern":"Unable to find blob path '<path>' in revision '<revision>'","errorType":"exception","errorClass":"NotFoundException","httpStatus":404,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/git/BlobIdent.java","lineNumber":59,"sourceCode":"\t\tthis.path = path;\n\t\tthis.mode = mode;\n\t}\n\t\n\tpublic BlobIdent(@Nullable String revision, @Nullable String path) {\n\t\tthis(revision, path, FileMode.REGULAR_FILE.getBits());\n\t}\n\t\n\tpublic BlobIdent() {\n\t}\n\t\n\tpublic BlobIdent(Project project, List<String> segments) {\n\t\tRevisionAndPath revisionAndPath = RevisionAndPath.parse(project, segments); \n\t\trevision = revisionAndPath.getRevision();\n\t\tpath = revisionAndPath.getPath();\n\t\tif (path != null) {\n\t\t\tmode = project.getMode(revision, path);\n\t\t\tif (mode == 0) {\n\t\t\t\tthrow new NotFoundException(\"Unable to find blob path '\" + path\n\t\t\t\t\t\t+ \"' in revision '\" + revision + \"'\");\n\t\t\t}\n\t\t} else {\n\t\t\tmode = FileMode.TREE.getBits();\n\t\t}\n\t}\n\t\n\tpublic boolean isTree() {\n\t\treturn mode != null && (FileMode.TYPE_MASK & mode) == FileMode.TYPE_TREE;\n\t}\n\t\n\tpublic boolean isGitLink() {\n\t\treturn mode != null && (FileMode.TYPE_MASK & mode) == FileMode.TYPE_GITLINK;\n\t}\n\t\n\tpublic boolean isSymbolLink() {\n\t\treturn mode != null && (FileMode.TYPE_MASK & mode) == FileMode.TYPE_SYMLINK;\n\t}","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/git/BlobIdent.java#L41-L77","documentation":"This BlobIdent constructor parses a revision-and-path segment list (e.g. from a URL), then calls project.getMode(revision, path) to look up the git file mode of the path at that revision. A mode of 0 means the path does not exist in the revision's tree, so a NotFoundException is thrown to signal a missing blob.","triggerScenarios":"Constructing new BlobIdent(project, segments) where the parsed path does not exist in the parsed revision: wrong file name, file exists only on another branch/commit, path was deleted or renamed, or typo in the URL path segment.","commonSituations":"Browsing a stale link to a file deleted after the link was made; requesting a file from a branch that doesn't contain it; typos in repository file paths in REST URLs; checking out a tag where the file never existed.","solutions":["Verify the path exists at that revision: project.getMode(revision, path) != 0, or use git ls-tree / list the directory before constructing BlobIdent.","Check the revision (branch/tag/commit) actually contains the file; try the default branch or the commit that added the file.","Catch NotFoundException and return a 404-style response or an empty-state UI for the caller.","If the file was moved, look up the new path (e.g. via rename detection or project history) and retry with the updated path."],"exampleFix":"// before\nBlobIdent ident = new BlobIdent(project, List.of(\"main\", \"docs\", \"removed.md\")); // throws if absent\n// after\nif (project.getMode(\"main\", \"docs/removed.md\") != 0) {\n    BlobIdent ident = new BlobIdent(project, List.of(\"main\", \"docs\", \"removed.md\"));\n} else {\n    throw new NotFoundException(\"docs/removed.md not on main\");\n}","handlingStrategy":"try-catch","validationCode":"if (project.getMode(revision, path) == 0) {\n    // path absent at revision: skip or return not-found\n}","typeGuard":"boolean blobExists(Project project, String revision, String path) {\n    return path != null && project.getMode(revision, path) != 0;\n}","tryCatchPattern":"try {\n    BlobIdent ident = new BlobIdent(project, segments);\n} catch (NotFoundException e) {\n    // render 404 / empty state\n}","preventionTips":["Check existence with project.getMode(revision, path) before constructing BlobIdent.","Resolve revision names to concrete commit ids before deep-linking.","Handle deleted/renamed paths with a fallback to the previous commit.","Validate URL path segments against the repository tree."],"tags":["git","not-found","blob","revision"],"backgroundTag":"resource-not-found","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}