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, err

View on GitHub (pinned to 81dcd7d73e)

Solutions

  1. Examine the wrapped %v driver error and address it (connectivity, permissions, doc limits).
  2. Verify database reachability and that the quads collection is writable by the configured credentials.
  3. Retry ApplyDeltas — the update is an upsert with an increment, so retrying the same delta is idempotent per quad.
  4. Split large delta batches into smaller ApplyDeltas calls to reduce per-transaction failure surface.
  5. 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

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


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