cayleygraph/cayley · error

unexpected node type: %T

Error message

unexpected node type: %T

What it means

QuadIterator was given a node reference (graph.Ref) that is not an Int64Value. The KV quadstore identifies nodes internally as uint64 IDs, so any other Ref implementation cannot be used to build a direction-scoped iterator, and an error iterator is returned instead.

Source

Thrown at graph/kv/iterators.go:82

		}
	}
	st, err := qs.Stats(ctx, false)
	if err != nil {
		return refs.Size{}, err
	}
	return refs.Size{
		Value: 1 + st.Quads.Value/2,
		Exact: false,
	}, nil
}

func (qs *QuadStore) QuadIterator(dir quad.Direction, v graph.Ref) iterator.Shape {
	if v == nil {
		return iterator.NewNull()
	}
	vi, ok := v.(Int64Value)
	if !ok {
		return iterator.NewError(fmt.Errorf("unexpected node type: %T", v))
	}
	// Find the best index for this direction.
	if ind := qs.bestIndexes([]quad.Direction{dir}); len(ind) == 1 {
		// this will scan the prefix automatically
		return qs.newQuadIterator(ind[0], []uint64{uint64(vi)})
	}
	// Fallback: iterate all quads and check the corresponding direction.
	return qs.newAllIterator(false, &constraint{
		dir: dir,
		val: vi,
	})
}

func (qs *QuadStore) OptimizeShape(ctx context.Context, s shape.Shape) (shape.Shape, bool) {
	switch s := s.(type) {
	case shape.QuadsAction:
		return qs.optimizeQuadsAction(s)
	}

View on GitHub (pinned to 81dcd7d73e)

Solutions

  1. Only pass Refs obtained from this same KV QuadStore (NameOf/Value lookups), not from other backends.
  2. Convert the node to the store's Int64Value via qs.ValueOf/lookup before building the iterator.
  3. Check that the graph.Ref you hold is not a wrapped or pointer type that fails the Int64Value assertion.

Example fix

// before
it := qs.QuadIterator(quad.Subject, someStringRef)
// after
val := qs.ValueOf(nodeName)
it := qs.QuadIterator(quad.Subject, val) // returns Int64Value for KV store
Defensive patterns

Strategy: type-guard

Validate before calling

if _, ok := ref.(kv.Int64Value); !ok { /* obtain a proper ref via qs.ValueOf before iterating */ }

Type guard

func isInt64Ref(r graph.Ref) bool { _, ok := r.(kv.Int64Value); return ok }

Try / catch

it := qs.QuadIterator(dir, ref)
if iterator.IsError(it) { ref = qs.ValueOf(name); it = qs.QuadIterator(dir, ref) }

Prevention

When it happens

Trigger: Calling qs.QuadIterator(dir, v) where v came from a different QuadStore implementation (e.g. a string-based store) or is any concrete type other than Int64Value.

Common situations: Mixing graph.Refs across backend implementations, using Node values from JSON/HTTP API responses without resolving them to KV int64 IDs, or after migrating stores between backends.

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/1f00c6a90ab28357. Report an issue: GitHub.