Lei Shu created TINKERPOP-3271:
----------------------------------

             Summary: subgraph() throws ClassCastException instead of a 
descriptive error for non-Edge input
                 Key: TINKERPOP-3271
                 URL: https://issues.apache.org/jira/browse/TINKERPOP-3271
             Project: TinkerPop
          Issue Type: Bug
            Reporter: Lei Shu


### Environment
Runtime reproduction on:
 
- TinkerPop 3.7.0 — Docker `tinkerpop/gremlin-server:3.7.0`
- TinkerPop 3.8.1 — Docker `tinkerpop/gremlin-server:latest`
 
### Description
`subgraph()` is documented as producing an edge-induced subgraph and must be 
called at edge steps. The fluent `GraphTraversal.subgraph(String)` method 
returns the existing `GraphTraversal<S,E>` without constraining `E` to `Edge`, 
so traversals producing non-Edge values can be constructed without a 
compile-time error and fail only at runtime. Regardless of whether compile-time 
enforcement is practical within the current DSL design, the runtime failure 
could identify the violated `subgraph()` input contract instead of exposing an 
internal `ClassCastException`.
 
### To Reproduce
Minimal (Integer input):
```groovy
g.inject(1).subgraph('sg').cap('sg').iterate()
```
 
Vertex input:
```groovy
g.addV().subgraph('sg').cap('sg').iterate()
```
 
Realistic (out() emits vertices into subgraph()):
```groovy
g.V().drop().iterate()
g.addV('N').property('v',1).as('a').addV('N').property('v',2).as('b').addE('X').from('a').to('b').iterate()
 
g.V().has('v',1).out('X').subgraph('sg').cap('sg')
```
 
### Expected
The step should reject a traverser value that is not an `Edge` with a 
descriptive argument or traversal-validation error identifying that 
`subgraph()` requires edge input, rather than exposing an internal 
`ClassCastException`.
 
### Actual
```
ClassCastException: class java.lang.Integer cannot be cast to class Edge
ClassCastException: class TinkerVertex cannot be cast to class Edge
at SubgraphStep.sideEffect(SubgraphStep.java:81)
```
 
### Root cause
`SubgraphStep` is typed for `Edge` traversers, but the traversal can be 
constructed with a non-Edge end type. During execution, `sideEffect()` 
retrieves the traverser value and passes it to `addEdgeToSubgraph(Edge)`. When 
that value is not an `Edge`, the runtime cast fails before a domain-specific 
validation error can be produced.
 
3.7.0 uses `SideEffectStep<Edge>`; 3.8.1 uses `SideEffectBarrierStep<Edge>`. 
Both pass `traverser.get()` directly to edge-accepting methods without runtime 
type checking.
 
### Workaround
Use `outE()` to ensure edge-only input:
```groovy
g.V().has('v',1).outE('X').subgraph('sg').cap('sg')
```
 
### Notes
- This is a `gremlin-core` issue, not TinkerGraph-specific
- No server crash, data corruption, or wrong results — error diagnosis 
improvement
- The input itself violates the documented constraint (subgraph requires edge 
input)
 
### Suggested JIRA fields
| Field | Value |
|-------|-------|
| Type | Improvement |
| Component | process |
| Priority | Minor |
| Affects Version/s | 3.7.0, 3.8.1 |
 



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to