cayleygraph/cayley · error
quad update failed: %v
Error message
quad update failed: %v
What it means
Returned by QuadStore.updateQuad when the Update(colQuads, key).Upsert(doc).Inc(setname, 1).Do(ctx) call fails. Every applied delta increments (or decrements via setname choice) a counter on the quad document; this error means the backing store rejected or could not complete that write.
Source
Thrown at graph/nosql/quadstore.go:284
func (qs *QuadStore) updateQuad(ctx context.Context, q quad.Quad, proc graph.Procedure) error {
var setname string
if proc == graph.Add {
setname = fldQuadAdded
} else if proc == graph.Delete {
setname = fldQuadDeleted
}
doc := nosql.Document{
fldSubject: nosql.String(hashOf(q.Subject)),
fldPredicate: nosql.String(hashOf(q.Predicate)),
fldObject: nosql.String(hashOf(q.Object)),
}
if l := hashOf(q.Label); l != "" {
doc[fldLabel] = nosql.String(l)
}
err := qs.db.Update(colQuads, getKeyForQuad(q)).Upsert(doc).
Inc(setname, 1).Do(ctx)
if err != nil {
err = fmt.Errorf("quad update failed: %v", err)
}
return err
}
func checkQuadValid(q nosql.Document) bool {
added, _ := asInt(q[fldQuadAdded])
deleted, _ := asInt(q[fldQuadDeleted])
return added > deleted
}
func (qs *QuadStore) checkValidQuad(ctx context.Context, key nosql.Key) (bool, error) {
q, err := qs.db.FindByKey(ctx, colQuads, key)
if err == nosql.ErrNotFound {
return false, nil
}
if err != nil {
err = fmt.Errorf("error checking quad validity: %v", err)
return false, errView on GitHub (pinned to 81dcd7d73e)
Solutions
- Examine the wrapped %v driver error and address it (connectivity, permissions, doc limits).
- Verify database reachability and that the quads collection is writable by the configured credentials.
- Retry ApplyDeltas — the update is an upsert with an increment, so retrying the same delta is idempotent per quad.
- Split large delta batches into smaller ApplyDeltas calls to reduce per-transaction failure surface.
- Check ctx deadlines; use a longer timeout for bulk load operations.
Example fix
// before
err = fmt.Errorf("quad update failed: %v", err)
// after
err = fmt.Errorf("quad update failed: %w", err)
// caller: retry transient failures
for i := 0; i < 3; i++ {
if err := store.ApplyDeltas(ctx, deltas, true); err == nil { break }
time.Sleep(time.Duration(1<<i) * 100 * time.Millisecond)
} Defensive patterns
Strategy: try-catch
Validate before calling
if err := ctx.Err(); err != nil { return err }
// verify store is writable
w := store.NewQuadWriter(ctx)
if w == nil { return errors.New("writer unavailable") }
w.Close() Try / catch
if err := store.ApplyDeltas(ctx, deltas, true); err != nil {
if isRetryable(err) { // network/timeout causes in wrapped %v
return retryWithBackoff(func() error { return store.ApplyDeltas(ctx, deltas, true) })
}
return err
} Prevention
- Retry upsert+inc deltas — they are idempotent per quad
- Keep delta batches small to limit blast radius of a failed write
- Ensure the quads collection is writable by configured credentials
- Avoid concurrent single-writer backend instances
- Set generous timeouts for bulk loads
When it happens
Trigger: ApplyDeltas hitting an unavailable/cancelled database, a quad key too large for the store, driver-level write errors (duplicate key, doc too big), or a read-only replica receiving the update.
Common situations: MongoDB primary stepdown mid-transaction; Bolt single-writer contention with concurrent Cayley instances; oversized quads (very long IRIs/values) exceeding the 16MB doc limit is rare but the inc path can still fail on connectivity.
Related errors
- error updating node: %v
- error cleaning up nodes: %v
- error checking quad validity: %v
- unexpected type for int field: %T
- unexpected type for pb field: %T
AI-assisted analysis of cayleygraph/cayley@81dcd7d73e (2026-09-06).
Data as JSON: /api/errors/136107a977c16b5a.
Report an issue: GitHub.