NationalSecurityAgency/ghidra · warning · SorterException
Not a total order: {} ?? {}
Error message
Not a total order: {} ?? {} What it means
Thrown by TopologicalSorter.checkTotal() (a checked SorterException) when the graph being sorted is not a total order: it computes all-pairs shortest paths and, for two vertices v1/v2, finds neither is reachable from the other (distF == null && distR == null). A total order requires every pair to be comparable, so two mutually-unreachable vertices mean the topological order is not unique/total. This is a structural validity check on the input graph, not a runtime fault.
Source
Thrown at Ghidra/Debug/ProposedUtils/src/main/java/ghidra/graph/algo/TopologicalSorter.java:103
visit(n);
}
}
/**
* Check that the solution is unique
*
* @throws SorterException if the solution is not unique
*/
protected void checkTotal() throws SorterException {
// This is probably not the most efficient, but this should only be once per message type
DijkstraShortestPathsAlgorithm<V, E> dijkstra =
new DijkstraShortestPathsAlgorithm<>(graph, GEdgeWeightMetric.unitMetric());
for (V v1 : graph.getVertices()) {
for (V v2 : graph.getVertices()) { // Maybe look into spliterator? to avoid double check
Double distF = dijkstra.getDistancesFromSource(v1).get(v2);
Double distR = dijkstra.getDistancesFromSource(v2).get(v1);
if (distF == null && distR == null) {
throw new SorterException("Not a total order", v1, v2);
}
}
}
}
/**
* Visit a vertex
*
* @param n the vertex
* @throws SorterException if a cycle is detected
*/
protected void visit(V n) throws SorterException {
visit(n, new LinkedList<>());
}
/**
* Visit a vertex, checking for a cycle
* View on GitHub (pinned to d5f144c24d)
Solutions
- Verify every vertex pair is comparable before calling sort; if incomparable pairs are acceptable, use a partial-order / non-unique sorter instead of one that calls checkTotal().
- Add explicit ordering edges between the two reported vertices (or their components) so a directed path exists at least one way.
- Remove disconnected vertices/components from the graph before sorting if they are irrelevant to the ordering.
- Catch SorterException (it is checked) and fall back to a non-total ordering strategy for that subgraph.
Example fix
// before
TopologicalSorter<V,E> s = new TopologicalSorter<>(graph);
s.sort(); // throws if two vertices are incomparable
// after: ensure every pair is comparable, or tolerate a partial order
try {
TopologicalSorter<V,E> s = new TopologicalSorter<>(graph);
s.sort();
} catch (SorterException e) {
// graph is only partially ordered; use a non-total topological order here
List<V> order = new DijkstraFiniteLoopGraphAlgorithm<>(graph).computeTopoOrder();
} Defensive patterns
Strategy: validation
Validate before calling
// Before sorting, verify every pair is comparable (total order)
DijkstraShortestPathsAlgorithm<V,E> d = new DijkstraShortestPathsAlgorithm<>(graph, GEdgeWeightMetric.unitMetric());
for (V v1 : graph.getVertices()) {
for (V v2 : graph.getVertices()) {
if (d.getDistancesFromSource(v1).get(v2) == null && d.getDistancesFromSource(v2).get(v1) == null) {
// incomparable pair: not a total order; do not call checkTotal()/sort
}
}
} Try / catch
try {
List<V> order = new TopologicalSorter<V,E>(graph).sort();
} catch (SorterException e) { // checked
// graph is not a total order; use a partial-order fallback
} Prevention
- Confirm the graph is connected and totally ordered before calling a total-order sorter.
- Use a partial-order sorter when incomparable pairs are acceptable.
- Add ordering edges between incomparable components if a unique order is required.
When it happens
Trigger: Invoking the sorter on a directed graph that has at least one pair of vertices with no directed path in either direction — e.g. disconnected components, two parallel branches that never rejoin, or sibling nodes with no ordering edge between them. checkTotal() is only meaningful when the caller requires a unique total order (see Javadoc 'if the solution is not unique').
Common situations: Building a dependency/ordering graph from program data (block ordering, instruction ordering) where some elements are genuinely incomparable; merging graphs from independent subtrees; feeding a DAG with multiple roots that never connect; expecting uniqueness from a graph that only admits a partial order.
Related errors
- Graph is cyclic: {}
- Failed to read {len} bytes at {addr}
- Trace does not contain referenced instruction: ({getStartSna
- Instruction has incompatible prototype at: ({getStartSnap},{
- Code units cannot overlap
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/88e01ab9b05783d1.
Report an issue: GitHub.