cayleygraph/cayley · error · DeltaError

ErrQuadNotExist

ErrQuadNotExist

Error message

quad does not exist

What it means

ErrQuadNotExist is returned when a DELETE delta references a quad that is not present in the quadstore. Removal of a non-existent quad cannot be applied, so the transaction fails with this sentinel error (often wrapped in graph.DeltaError).

Source

Thrown at graph/quadwriter.go:84

type Handle struct {
	QuadStore
	QuadWriter
}

type IgnoreOpts struct {
	IgnoreDup, IgnoreMissing bool
}

func (h *Handle) Close() error {
	err := h.QuadWriter.Close()
	h.QuadStore.Close()
	return err
}

var (
	ErrQuadExists    = errors.New("quad exists")
	ErrQuadNotExist  = errors.New("quad does not exist")
	ErrInvalidAction = errors.New("invalid action")
	ErrNodeNotExists = errors.New("node does not exist")
)

// DeltaError records an error and the delta that caused it.
type DeltaError struct {
	Delta Delta
	Err   error
}

func (e *DeltaError) Error() string {
	if !e.Delta.Quad.IsValid() {
		return e.Err.Error()
	}
	return e.Delta.Action.String() + " " + e.Delta.Quad.String() + ": " + e.Err.Error()
}

func (e *DeltaError) Unwrap() error {

View on GitHub (pinned to 81dcd7d73e)

Solutions

  1. Verify the quad exists (qs lookup) before appending the Delete delta
  2. Treat as idempotent: filter the error with graph.IsQuadNotExist(err) and continue when absence is acceptable
  3. Ensure the Add that created the quad actually succeeded before queuing its Delete (check earlier deltas' errors)
  4. Re-fetch current quad state instead of relying on cached results that may be stale

Example fix

// before
err := qw.ApplyDeltas([]graph.Delta{{Action: graph.Delete, Quad: q}})
// after
err := qw.ApplyDeltas([]graph.Delta{{Action: graph.Delete, Quad: q}})
if err != nil && !graph.IsQuadNotExist(err) {
    return err // deleting a missing quad is OK
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check before deleting
if qs.QuadExists(quad) { // or lookup the quad first
    return qw.ApplyDeltas([]graph.Delta{{Action: graph.Delete, Quad: quad}})
}
return nil

Type guard

func isQuadNotExist(err error) bool { return errors.Is(err, graph.ErrQuadNotExist) || graph.IsQuadNotExist(err) }

Try / catch

err := qw.ApplyDeltas(deltas)
if err != nil {
    if graph.IsQuadNotExist(err) {
        // already gone: treat as success
    } else {
        return err
    }
}

Prevention

When it happens

Trigger: Applying a Delete delta for a quad that was never inserted or was already removed; gaedatastore ApplyDeltas hitting the default removal path where the quad lookup fails; writers that remove before add in a rollback path where the add never succeeded.

Common situations: Removing a quad twice (e.g. duplicate delete in a batch); deleting based on stale query results; rebase/rollback code that deletes quads that failed to insert; tests using mis-match (mis) expectations where the missing quad is tolerated.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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