cayleygraph/cayley · error

gae quad: token not valid

Error message

gae quad: token not valid

What it means

Quad requires a *Token with Kind quadKind to construct the datastore key for the QuadEntry. Any other ref type or token kind yields this error, and the quad cannot be fetched.

Source

Thrown at graph/gaedatastore/quadstore.go:489

	// TODO (panamafrancis) implement a cache

	node := new(NodeEntry)
	err := datastore.Get(qs.context, key, node)
	if err != nil {
		return nil, err
	}
	return quad.Raw(node.Name), nil
}

func (qs *QuadStore) Quad(val graph.Ref) (quad.Quad, error) {
	if qs.context == nil {
		return quad.Quad{}, errors.New("context is nil, graph is not correctly initialized")
	}
	var key *datastore.Key
	if t, ok := val.(*Token); ok && t.Kind == quadKind {
		key = qs.createKeyFromToken(t)
	} else {
		return quad.Quad{}, errors.New("gae quad: token not valid")
	}

	q := new(QuadEntry)
	err := datastore.Get(qs.context, key, q)
	if err != nil {
		// Red herring error : ErrFieldMismatch can happen when a quad exists but a field is empty
		if _, ok := err.(*datastore.ErrFieldMismatch); !ok {
			return quad.Quad{}, err
		}
	}
	var label interface{}
	if q.Label != "" {
		label = q.Label
	}
	return quad.Make(
		q.Subject,
		q.Predicate,
		q.Object,

View on GitHub (pinned to 81dcd7d73e)

Solutions

  1. Ensure the ref comes from quad iteration / quadsOf paths, i.e. has Kind quadKind.
  2. Type-check before calling: t, ok := val.(*Token); ok && t.Kind == quadKind.
  3. Use NameOf for nodeKind tokens instead.
  4. Fix serialization that flattens tokens and loses Kind information.

Example fix

// before
q, err := qs.Quad(nodeToken)
// after
if t, ok := ref.(*Token); ok && t.Kind == quadKind {
    q, err = qs.Quad(ref)
}
Defensive patterns

Strategy: type-guard

Validate before calling

if t, ok := ref.(*Token); !ok || t.Kind != quadKind {
    return errors.New("Quad requires a quadKind Token")
}

Type guard

func isQuadToken(ref graph.Ref) bool {
    t, ok := ref.(*Token)
    return ok && t.Kind == quadKind
}

Try / catch

q, err := qs.Quad(ref)
if err != nil {
    if strings.Contains(err.Error(), "token not valid") {
        // wrong token kind; use NameOf for node tokens
    }
    return err
}

Prevention

When it happens

Trigger: Passing a nodeKind Token, a raw hash ref, or a PreFetchedValue into Quad; mixing node and quad tokens when caching references.

Common situations: Confusing results of NameFor (node tokens) with QuadIterator tokens (quad tokens); refactoring across the old Value/Key API; storing token strings and re-parsing them incorrectly.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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