cayleygraph/cayley · error
error fetching quad %#v: %w
Error message
error fetching quad %#v: %w
What it means
After asserting the ref is a *proto.Primitive, Quad reads the primitive and assembles the full quad via a KV transaction view. Any error from that read/assembly (other than ErrNotFound, which yields a zero quad) is wrapped with the primitive key for debugging. This indicates the primitive exists as a ref but could not be materialized from storage.
Source
Thrown at graph/kv/quadstore.go:391
}
func (qs *QuadStore) Quad(k graph.Ref) (quad.Quad, error) {
key, ok := k.(*proto.Primitive)
if !ok {
return quad.Quad{}, fmt.Errorf("passed value was not a quad primitive: %T", k)
}
ctx := context.TODO()
var v quad.Quad
err := kv.View(ctx, qs.db, func(tx kv.Tx) error {
var err error
v, err = qs.primitiveToQuad(ctx, tx, key)
return err
})
if err == kv.ErrNotFound {
err = nil
}
if err != nil {
err = fmt.Errorf("error fetching quad %#v: %w", key, err)
}
return v, err
}
func (qs *QuadStore) primitiveToQuad(ctx context.Context, tx kv.Tx, p *proto.Primitive) (quad.Quad, error) {
q := &quad.Quad{}
for _, dir := range quad.Directions {
v := p.GetDirection(dir)
val, err := qs.getValFromLog(ctx, tx, v)
if err != nil {
return *q, err
}
q.Set(dir, val)
}
return *q, nil
}
func (qs *QuadStore) getValFromLog(ctx context.Context, tx kv.Tx, k uint64) (quad.Value, error) {View on GitHub (pinned to 81dcd7d73e)
Solutions
- Inspect the wrapped cause to distinguish DB errors from malformed primitive data
- Check the database file integrity (bolt.ConsistencyCheck or equivalent) and rebuild if corrupt
- If the ref is dangling, re-run iterators to get fresh valid refs
- Treat an empty returned quad with nil error as 'not found' — that is the ErrNotFound path
Example fix
// before
q, err := qs.Quad(prim) // opaque error
// after
q, err := qs.Quad(prim)
if err != nil {
var kvErr error
errors.As(err, &kvErr) // unwrap to see the underlying KV failure
log.Printf("quad fetch failed for %v: %v", prim, err)
} Defensive patterns
Strategy: try-catch
Validate before calling
if p, ok := k.(*proto.Primitive); !ok || p == nil {
return errors.New("not a primitive ref")
} Try / catch
q, err := qs.Quad(prim)
if err != nil {
// err is wrapped: use errors.As/errors.Is to inspect the KV cause
if errors.Is(err, context.DeadlineExceeded) { /* retry */ }
return fmt.Errorf("quad fetch failed: %w", err)
}
// note: err == nil with empty quad means not found (kv.ErrNotFound swallowed) Prevention
- Remember ErrNotFound is converted to a zero-value quad with nil error — check for the empty quad
- Run DB integrity checks periodically on Bolt/badger files
- Re-acquire refs from fresh iterators rather than caching long-lived primitives
When it happens
Trigger: Calling QuadStore.Quad with a valid *proto.Primitive whose KV read fails: the view transaction errors, primitiveToQuad fails on malformed/partial data, or the DB returns an I/O error. (kv.ErrNotFound is deliberately swallowed and returns an empty quad.)
Common situations: Dangling refs pointing at primitives deleted from the DB; corruption or partial writes in the KV file; concurrent modification; disk I/O problems.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- ErrNoBucket
- ErrEmptyPath
- kv: data version is out of date. Run cayleyupgrade for your
- cannot decode indexes: %v
- cannot get horizon value: %v
AI-assisted analysis of cayleygraph/cayley@81dcd7d73e (2026-09-06).
Data as JSON: /api/errors/a2e299a5745e2ce5.
Report an issue: GitHub.