cayleygraph/cayley · error
node tokens not valid
Error message
node tokens not valid
What it means
QuadDirection can only resolve directions on quad tokens (which encode a quad and an offset). A token of Kind nodeKind represents a standalone node value, which has no containing quad and thus no direction to read; passing such a token is rejected with this error.
Source
Thrown at graph/gaedatastore/quadstore.go:561
err := datastore.Get(qs.context, key, n)
if err != nil && err != datastore.ErrNoSuchEntity {
return refs.Size{}, err
}
return refs.Size{Value: n.Size, Exact: true}, nil
}
func (qs *QuadStore) Close() error {
qs.context = nil
return nil
}
func (qs *QuadStore) QuadDirection(val graph.Ref, dir quad.Direction) (graph.Ref, error) {
t, ok := val.(*Token)
if !ok {
return nil, errors.New("token not valid")
}
if t.Kind == nodeKind {
return nil, errors.New("node tokens not valid")
}
var offset int
switch dir {
case quad.Subject:
offset = 0
case quad.Predicate:
offset = (quad.HashSize * 2)
case quad.Object:
offset = (quad.HashSize * 2) * 2
case quad.Label:
offset = (quad.HashSize * 2) * 3
}
sub := t.Hash[offset : offset+(quad.HashSize*2)]
return &Token{Kind: nodeKind, Hash: sub}, nil
}
View on GitHub (pinned to 81dcd7d73e)
Solutions
- Check the token Kind before calling: only invoke QuadDirection when tok.Kind != nodeKind.
- For node tokens there is nothing to resolve; handle them separately (e.g. return the node itself or skip).
- Refactor the caller to track whether a ref came from a quad result or a value result.
Example fix
// before
ref, err := qs.QuadDirection(tok, quad.Subject)
// after
if tok.(*gaedatastore.Token).Kind == gaedatastore.NodeKind {
return nil, nil // node token: no direction to resolve
}
ref, err := qs.QuadDirection(tok, quad.Subject) Defensive patterns
Strategy: type-guard
Validate before calling
if t, ok := ref.(*gaedatastore.Token); ok && t.Kind == gaedatastore.NodeKind {
return nil // node token: nothing to resolve
} Type guard
func isNodeToken(ref graph.Ref) bool {
t, ok := ref.(*gaedatastore.Token)
return ok && t.Kind == gaedatastore.NodeKind
} Try / catch
ref, err := qs.QuadDirection(val, dir)
if err != nil && err.Error() == "node tokens not valid" {
return val, nil // it's a node: return as-is
} Prevention
- Check token Kind before resolving directions.
- Separate handling for node results vs quad results in iteration code.
- Document that QuadDirection is quad-token-only.
When it happens
Trigger: Calling QuadDirection(val, dir) where val is a *Token whose Kind equals nodeKind — i.e. a node token obtained for a standalone value (e.g. from NameOf/value lookups) rather than a quad-side token.
Common situations: Iterating results that contain both node and quad refs and blindly calling QuadDirection on all of them; confusing node tokens (produced by QuadStore.ValueOfNode equivalents) with quad tokens.
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
- cannot count iterator without a valid context
- varint: overflow
- ErrNoBucket
- ErrEmptyPath
- kv: data version is out of date. Run cayleyupgrade for your
AI-assisted analysis of cayleygraph/cayley@81dcd7d73e (2026-09-06).
Data as JSON: /api/errors/4f78cd6f08df2cea.
Report an issue: GitHub.