theonedev/onedev · error · IllegalStateException

Cannot combine topo sort with topo-keep-branch-together sort

Error message

Cannot combine topo sort with topo-keep-branch-together sort.

What it means

Thrown by StartGenerator.next() when the walk's sort order contains both RevSort.TOPO and RevSort.TOPO_KEEP_BRANCH_TOGETHER. These two topological ordering strategies are mutually exclusive; the generator pipeline cannot implement both at once, so JGit throws IllegalStateException when the walk starts.

Source

Thrown at server-core/src/main/java/org/eclipse/jgit/revwalk/StartGenerator.java:134

		} else {
			g = new PendingGenerator(w, pending, rf, pendingOutputType);

			if (walker.hasRevSort(RevSort.BOUNDARY)) {
				// Because the boundary generator may produce uninteresting
				// commits we cannot allow the pending generator to dispose
				// of them early.
				//
				((PendingGenerator) g).canDispose = false;
			}
		}

		if ((g.outputType() & NEEDS_REWRITE) != 0) {
			g = new RewriteGenerator(g);
		}

		if (walker.hasRevSort(RevSort.TOPO)
				&& walker.hasRevSort(RevSort.TOPO_KEEP_BRANCH_TOGETHER)) {
			throw new IllegalStateException(JGitText
					.get().cannotCombineTopoSortWithTopoKeepBranchTogetherSort);
		}

		if (walker.hasRevSort(RevSort.TOPO)
				&& (g.outputType() & SORT_TOPO) == 0) {
			g = new TopoSortGenerator(g);
		} else if (walker.hasRevSort(RevSort.TOPO_KEEP_BRANCH_TOGETHER)
				&& (g.outputType() & SORT_TOPO) == 0) {
			g = new TopoNonIntermixSortGenerator(g);
		}
		if (walker.hasRevSort(RevSort.REVERSE))
			g = new LIFORevQueue(g);
		if (boundary)
			g = new BoundaryGenerator(w, g);
		else if (uninteresting) {
			// Try to protect ourselves from uninteresting commits producing
			// due to clock skew in the commit time stamps. Delay such that
			// we have a chance at coloring enough of the graph correctly,

View on GitHub (pinned to d44925c47c)

Solutions

  1. Remove one of the two sort(RevSort.TOPO / RevSort.TOPO_KEEP_BRANCH_TOGETHER) calls, keeping only the semantics you need
  2. Reset the walk's sort order (or create a fresh RevWalk) when the desired ordering changes
  3. In user-facing tools, treat the two orderings as mutually exclusive options and reject the combination in configuration parsing

Example fix

// before
walk.sort(RevSort.TOPO);
walk.sort(RevSort.TOPO_KEEP_BRANCH_TOGETHER);
// after
walk.sort(RevSort.TOPO_KEEP_BRANCH_TOGETHER); // implies topological order; drop plain TOPO
Defensive patterns

Strategy: validation

Validate before calling

if (sorts.contains(RevSort.TOPO) && sorts.contains(RevSort.TOPO_KEEP_BRANCH_TOGETHER)) {
    throw new IllegalArgumentException("Choose either TOPO or TOPO_KEEP_BRANCH_TOGETHER, not both");
}

Try / catch

try (RevWalk walk = new RevWalk(repo)) {
    ...
} catch (IllegalStateException e) {
    // drop one of the sort orders on a fresh walk and retry
}

Prevention

When it happens

Trigger: Calling RevWalk.sort(RevSort.TOPO) and RevWalk.sort(RevSort.TOPO_KEEP_BRANCH_TOGETHER) on the same walk, then iterating. Note sort() accumulates flags, so calling both — even conditionally from different code paths — triggers this.

Common situations: Merging sort requirements from user-facing options (e.g. '--topo-order' plus a branch-grouping option) into one RevWalk; incremental code that adds sorts without clearing previous ones.

Related errors


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