theonedev/onedev · warning · BadRequestException
Path '" + blobIdent.path + "' is a tree"
Error message
Path '" + blobIdent.path + "' is a tree"
What it means
getBlob in DefaultGitService resolves a path in a commit's tree and returns file content. If the path resolves to a tree (directory) rather than a blob or gitlink, there is no blob content to return, so a BadRequestException is thrown stating the path is a tree. Callers are expected to pass file paths, not directory paths.
Source
Thrown at server-core/src/main/java/io/onedev/server/git/service/DefaultGitService.java:942
return submodules;
}
private Blob getBlob(String path) {
Repository repository = getRepository(projectId);
try (RevWalk revWalk = new RevWalk(repository)) {
Blob blob = null;
RevCommit commit = GitUtils.parseCommit(revWalk, revId);
if (commit != null) {
TreeWalk treeWalk = TreeWalk.forPath(repository, path, commit.getTree());
if (treeWalk != null) {
BlobIdent blobIdent = new BlobIdent(revId.name(), path, treeWalk.getRawMode(0));
ObjectId blobId = treeWalk.getObjectId(0);
if (blobIdent.isGitLink()) {
String url = getSubmodules().get(blobIdent.path);
String hash = blobId.name();
blob = new Blob(blobIdent, blobId, new Submodule(url, hash).toString().getBytes());
} else if (blobIdent.isTree()) {
throw new BadRequestException("Path '" + blobIdent.path + "' is a tree");
} else {
blob = new Blob(blobIdent, blobId, treeWalk.getObjectReader());
}
}
}
return blob;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public Blob call() {
return getBlob(path);
}
});
}View on GitHub (pinned to d44925c47c)
Solutions
- Check the path's type first (tree vs blob, e.g. BlobIdent.isTree()) and only fetch blobs for files.
- If a directory was intended, enumerate its children instead of requesting blob content.
- Fix the path to point to an actual file inside the directory.
Example fix
// before Blob blob = blobService.getBlob(projectId, revision, path); // path may be a dir // after BlobIdent ident = blobService.getBlobIdent(projectId, revision, path); if (ident != null && ident.isTree()) throw new BadRequestException(path + " is a directory, not a file"); Blob blob = blobService.getBlob(projectId, revision, path);
Defensive patterns
Strategy: type-guard
Validate before calling
BlobIdent ident = blobService.getBlobIdent(projectId, revision, path); if (ident == null || ident.isTree()) throw new BadRequestException(path + " is not a file at " + revision);
Type guard
function isFileBlob(ident) { return ident != null && !ident.isTree() && !ident.isGitLink(); } Try / catch
try { return blobService.getBlob(projectId, revision, path); } catch (BadRequestException e) { return listTreeChildren(revision, path); } Prevention
- Resolve the blob ident and check isTree() before requesting content
- Never pass directory paths or the empty path to getBlob
- Handle file->directory transitions when pathing against old revisions
When it happens
Trigger: Calling getBlob/BlobService.getBlob with a path that exists in the revision as a directory, e.g. requesting blob content for 'src' when 'src' is a folder, or passing an empty/root-like path.
Common situations: API clients assuming every path is a file; web UI deep-links to a path that was later converted from file to directory; scripted downloads iterating paths without checking entry type; typos where a trailing file name is missing.
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
- Unable to find blob path '<path>' in revision '<revision>'
- Unable to find blob path '' in revision ''
- Unable to find blob ident:
- Can only compare with common ancestor when different project
- Path '${treePath}' does not exist or is not a tree.
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/352f1da9d6af7722.
Report an issue: GitHub.