You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# Fix #4645 - shortestPath edge:true ClassCastException on BOTH direction with empty side
2
+
3
+
## Issue
4
+
5
+
`shortestPath(..., {'direction':'BOTH','edge':true})` throws `ClassCastException` when one of the two directional sub-queries returns an empty edge list.
6
+
7
+
## Root Cause (two bugs)
8
+
9
+
**Bug 1 - ClassCastException:**`EdgeToVertexIterable.iterator()` unconditionally cast the result of `edges.iterator()` to `EdgeIterator`:
When `direction:BOTH`, `SQLFunctionShortestPath.getVerticesAndEdges()` recurses into `OUT` and `IN`. For a vertex that has only an outgoing edge, the `IN` side returns `GraphEngine.EMPTY_EDGE_LIST`. That list's `iterator()` returns `Collections.emptyIterator()` which is NOT an `EdgeIterator`, causing `ClassCastException`.
14
+
15
+
**Bug 2 - Wrong vertex returned:**`EdgeToVertexIterator.next()` called `edge.getVertex(direction)` where `direction` is the traversal direction. For an OUT traversal from vertex 'a', this returns 'a' (the OUT/source end) rather than the neighbor 'b' (the IN/destination end). The BFS made no progress because every "neighbor" was the current vertex itself.
16
+
17
+
## Fix
18
+
19
+
**EdgeToVertexIterable:** check `instanceof ResettableIterator` (the common supertype of `EdgeIterator` and `EdgeIteratorFilter`) before casting. `EMPTY_EDGE_LIST.iterator()` returns `Collections.emptyIterator()` which is not a `ResettableIterator`, so it returns an empty iterator instead.
20
+
21
+
**EdgeToVertexIterator:** change field type to `ResettableIterator<Edge>` and fix `next()` to use the opposite direction (`direction == OUT ? IN : OUT`), which correctly returns the neighbor vertex.
22
+
23
+
## Files Changed
24
+
25
+
-`engine/src/main/java/com/arcadedb/graph/EdgeToVertexIterable.java` - guard against non-ResettableIterator (empty edge list)
26
+
-`engine/src/main/java/com/arcadedb/graph/EdgeToVertexIterator.java` - accept `ResettableIterator<Edge>`; fix `next()` to return the opposite-end vertex
27
+
-`engine/src/test/java/com/arcadedb/function/sql/graph/SQLFunctionShortestPathTest.java` - regression test for `edge:true` + `direction:BOTH` with asymmetric edges
28
+
29
+
## Verification
30
+
31
+
Run: `mvn test -pl engine -Dtest=SQLFunctionShortestPathTest`
32
+
33
+
Results: 14 tests run, 0 failures, 0 errors.
34
+
35
+
## PR
36
+
37
+
https://github.com/ArcadeData/arcadedb/pull/4646
38
+
39
+
## Review cycles
40
+
41
+
### Cycle 1 - HEAD 73b365f4 (gemini-code-assist review + claude review)
42
+
43
+
Applied:
44
+
- Gemini (high): `EdgeToVertexIterable` now throws `IllegalArgumentException` for a non-empty, non-resettable iterator instead of silently returning an empty iterator (with explanatory comment - also subsumes Claude's "add a comment" suggestion).
45
+
- Claude: extracted the direction flip in `EdgeToVertexIterator.next()` to a `neighborEnd` local variable.
46
+
- Claude: regression test now asserts the middle element equals the edge RID.
47
+
- Claude: added `edgeTrueDirectionBothReverseAsymmetric` (search b->a, empty OUT side exercises the IN half).
48
+
- Claude: added `edgeTrueDirectionIn` (pure IN direction with edge:true).
49
+
50
+
Skipped with rationale:
51
+
- Claude suggested removing this `docs/4645-*.md` file. Kept it: the `resolve-issue` workflow creates this tracking doc by design and folds review-cycle history into it. The bot is unaware of this committed convention.
52
+
53
+
### Cycle 2 - HEAD 705af13ba
54
+
55
+
- claude-review workflow re-ran on 705af13ba and completed clean (no new actionable comments).
56
+
- gemini's consumer bot (being sunset) did not auto re-trigger on the new SHA; its single cycle-1 inline concern (silent-swallow on `EdgeToVertexIterable`) was already resolved in cycle 1 and a resolution reply was posted in the thread.
57
+
- No code changes required.
58
+
59
+
## CI status triage (HEAD 705af13ba)
60
+
61
+
7 CI test failures, all confirmed unrelated to this change (which only touches the shortestPath edge-to-vertex traversal path):
62
+
63
+
Pre-existing on main (HEAD 898aebe60, verified by running on a clean main checkout):
Change-specific verification: `SQLFunctionShortestPathTest` (14 tests) and the broader graph suite (342 tests) all pass locally.
75
+
76
+
## Final state
77
+
78
+
clean-approval - all actionable bot feedback addressed; cycle-2 re-review clean; CI failures triaged as pre-existing/flaky and unrelated. Merge is the developer's decision.
0 commit comments