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.

Solutions

  1. Ensure the QuadStore used to execute the query is the same kv.QuadStore that produced the IndexScan plan.
  2. Re-plan/re-optimize the query against the current store instead of reusing a plan built for the KV backend.
  3. 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

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


AI-assisted analysis of cayleygraph/cayley@81dcd7d73e (2026-09-06). Data as JSON: /api/errors/7e053d8bbac2aaf3. Report an issue: GitHub.

Appendix: 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)