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

  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.