cayleygraph/cayley · error
expected KV quadstore, got: %T
Error message
expected KV quadstore, got: %T
What it means
IndexScan.BuildIterator received a QuadStore that is not a *kv.QuadStore. IndexScan is a KV-specific iterator shape that only knows how to replay index scans against the KV backend, so any other QuadStore implementation yields an error iterator.
Source
Thrown at graph/kv/iterators.go:135
for _, d := range ind[0].Dirs {
v, ok := s.Filter[d].(Int64Value)
if !ok {
return s, false
}
quads.Values = append(quads.Values, uint64(v))
}
return s.SimplifyFrom(quads), true
}
type IndexScan struct {
Index QuadIndex
Values []uint64
}
func (s IndexScan) BuildIterator(qs graph.QuadStore) iterator.Shape {
kqs, ok := qs.(*QuadStore)
if !ok {
return iterator.NewError(fmt.Errorf("expected KV quadstore, got: %T", qs))
}
return kqs.newQuadIterator(s.Index, s.Values)
}
func (s IndexScan) Optimize(ctx context.Context, r shape.Optimizer) (shape.Shape, bool) {
return s, false
}
View on GitHub (pinned to 81dcd7d73e)
Solutions
- Ensure the QuadStore used to execute the query is the same kv.QuadStore that produced the IndexScan plan.
- Re-plan/re-optimize the query against the current store instead of reusing a plan built for the KV backend.
- Do not mix backends: rebuild the session so qs is *graph.kv.QuadStore before executing.
Example fix
// before
it := kvIndexScan.BuildIterator(memoryStore) // wrong store
// after
if _, ok := memoryStore.(*kv.QuadStore); !ok { plan = replan(memoryStore) }
it := kvIndexScan.BuildIterator(kvStore) Defensive patterns
Strategy: type-guard
Validate before calling
if _, ok := qs.(*kv.QuadStore); !ok { replan against the actual store } Type guard
func isKVStore(qs graph.QuadStore) bool { _, ok := qs.(*kv.QuadStore); return ok } Try / catch
it := scan.BuildIterator(qs)
if iterator.IsError(it) { plan, _ = shape.BuildPlan(qs); it = plan.BuildIterator(qs) } Prevention
- Keep plan construction and execution on the same QuadStore instance/backend.
- Do not serialize and reuse optimized plans across different backends.
- In tests, inject the same store type the iterator shapes were built for.
When it happens
Trigger: Running an optimized query plan containing an IndexScan shape against a non-KV QuadStore, typically when iterator shapes are serialized/moved between sessions or backends, or when a session's store was swapped after planning.
Common situations: Mixing cayley backends (memory vs kv) in one process, reusing a persisted/optimized query plan across stores, or tests injecting a mock QuadStore into a KV-shaped plan.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- unexpected node type: %T
- token not valid
- gae quad: token not valid
- must execute a Step
- must execute a IteratorStep or PathStep
AI-assisted analysis of cayleygraph/cayley@81dcd7d73e (2026-09-06).
Data as JSON: /api/errors/7e053d8bbac2aaf3.
Report an issue: GitHub.