theonedev/onedev · error · IllegalArgumentException

Path '${treePath}' does not exist or is not a tree.

Error message

Path '${treePath}' does not exist or is not a tree.

What it means

LastCommitsOfChildren computes the last commit that touched each child of a directory in a git tree. Before walking, it resolves the given treePath against the 'until' commit's tree with TreeWalk.forPath; if the path does not exist, or exists but is a blob (file) rather than a directory, it throws this IllegalArgumentException. Only an existing directory (FileMode.TREE) can have children.

Source

Thrown at server-core/src/main/java/org/eclipse/jgit/revwalk/LastCommitsOfChildren.java:91

			@Nullable String treePath, @Nullable final Cache cache) {
		try (RevWalk revWalk = new RevWalk(repo)) {
			treePath = GitUtils.normalizePath(treePath);
			if (treePath == null) 
				treePath = "";
			
			final byte[] treePathRaw = Constants.encode(treePath);
			final Set<String> children = new HashSet<>();
			final Set<String> modifiedChildren = new HashSet<>();

			RevCommit untilCommit = revWalk.parseCommit(until);

			/*
			 * Find out child directory or file names under the tree
			 */
			if (treePath.length() != 0) {
				TreeWalk treeWalk = TreeWalk.forPath(repo, treePath, untilCommit.getTree());
				if (treeWalk == null || !FileMode.TREE.equals(treeWalk.getFileMode(0)))
					throw new IllegalArgumentException("Path '" + treePath + "' does not exist or is not a tree.");
				treeWalk.enterSubtree();
				treeWalk.setRecursive(false);
				while (treeWalk.next())
					children.add(treeWalk.getPathString().substring(treePath.length()+1));
			} else {
				try (TreeWalk treeWalk = new TreeWalk(repo)) {
					treeWalk.addTree(untilCommit.getTree());
					treeWalk.setRecursive(false);
					while (treeWalk.next())
						children.add(treeWalk.getPathString().substring(treePath.length()));
				}
			}
			
			revWalk.markStart(untilCommit);
			revWalk.setRewriteParents(false);

			/* 
			 * Records last commits info of first encountered commit in cache, and we 

View on GitHub (pinned to d44925c47c)

Solutions

  1. Verify the path exists and is a directory in the same commit passed as untilCommit before constructing LastCommitsOfChildren (TreeWalk.forPath(repo, path, untilCommit.getTree()) != null and FileMode.TREE.equals(tw.getFileMode(0))).
  2. Normalize the path: strip leading/trailing '/' and resolve '.'/'..' segments.
  3. If the path is a file, request last-commit data for the file's parent directory instead, or use a file-oriented API.
  4. Handle the case where the directory was deleted in untilCommit by falling back to the commit where it last existed.
  5. Catch IllegalArgumentException as a signal to return 404/not-a-directory to the caller.

Example fix

// before
LastCommitsOfChildren children = new LastCommitsOfChildren(project.getRepository(), commit, path);
// after
try (RevWalk rw = new RevWalk(project.getRepository())) {
    RevCommit c = rw.parseCommit(commit.getId());
    if (!path.isEmpty()) {
        TreeWalk tw = TreeWalk.forPath(project.getRepository(), path, c.getTree());
        if (tw == null || !FileMode.TREE.equals(tw.getFileMode(0)))
            throw new NotFoundException("Path is not a directory in commit " + c.getName());
    }
}
LastCommitsOfChildren children = new LastCommitsOfChildren(project.getRepository(), commit, path);
Defensive patterns

Strategy: validation

Validate before calling

boolean isDirectoryIn(Repository repo, RevCommit c, String path) throws IOException {
    if (path == null || path.isEmpty()) return true;
    String p = StringUtils.strip(path, "/");
    try (TreeWalk tw = TreeWalk.forPath(repo, p, c.getTree())) {
        return tw != null && FileMode.TREE.equals(tw.getFileMode(0));
    }
}

Type guard

boolean isTreeMode(TreeWalk tw) { return tw != null && FileMode.TREE.equals(tw.getFileMode(0)); }

Try / catch

try {
    return new LastCommitsOfChildren(repo, commit, path);
} catch (IllegalArgumentException e) {
    throw new ResourceNotFoundException("Directory not found in commit: " + path);
}

Prevention

When it happens

Trigger: Calling new LastCommitsOfChildren(repo, untilCommit, path) where path is empty-but-null-adjacent misspellings aside: (1) the path does not exist in the commit's tree (deleted/renamed/typo), (2) the path is a file, not a directory, (3) the path exists only in another branch/commit than untilCommit, (4) leading/trailing slashes or non-normalized paths that JGit cannot resolve.

Common situations: Rendering a file-browser 'last modified per entry' view in OneDev where a user-supplied path param points to a file or a stale path after a refactor; caching a directory path from an older commit and reusing it against a newer untilCommit where the directory was removed; building the path by string concatenation producing double slashes.

Related errors


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