cayleygraph/cayley · error · DeltaError

ErrQuadExists

ErrQuadExists

Error message

quad exists

What it means

ErrQuadExists is returned when an ADD delta tries to insert a quad whose subject-predicate-object-context already exists in the quadstore. Cayley stores each unique quad once; inserting a duplicate is rejected rather than silently re-adding. It is typically wrapped in a graph.DeltaError carrying the offending delta.

Source

Thrown at graph/quadwriter.go:83

}

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()
}

View on GitHub (pinned to 81dcd7d73e)

Solutions

  1. Check for existence first with qs.Quad exists/contains lookup before adding, or filter deltas through graph.NewRemover/Add logic
  2. Skip or downgrade duplicates: pre-check each quad with a lookup and drop Add deltas for quads already stored
  3. For gaedatastore, set ignoreOpts.IgnoreDup so duplicate adds are treated as no-ops
  4. Compare errors with graph.IsQuadExist(err) and treat as success when duplicates are acceptable

Example fix

// before
err := qw.ApplyDeltas([]graph.Delta{{Action: graph.Add, Quad: q}})
// after
if !qs.QuadExists(q) { // or use graph.IsQuadExist(err) and ignore
    err = qw.ApplyDeltas([]graph.Delta{{Action: graph.Add, Quad: q}})
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check before adding
if qs.QuadExists(quad) {
    return nil // skip duplicate
}
return qw.ApplyDeltas([]graph.Delta{{Action: graph.Add, Quad: quad}})

Type guard

func isQuadExists(err error) bool { return errors.Is(err, graph.ErrQuadExists) || graph.IsQuadExist(err) }

Try / catch

err := qw.ApplyDeltas(deltas)
if err != nil {
    if graph.IsQuadExist(err) {
        // duplicate add: safe to ignore or log
    } else {
        return err
    }
}

Prevention

When it happens

Trigger: Calling ApplyDeltas (or ApplyAddDeltas / a writer that uses it) with an Add delta for a quad already present in the store; in gaedatastore ApplyDeltas when the quad lookup finds the quad and IgnoreDup is not set; via WriteQuad with the Add action on an existing quad.

Common situations: Replaying the same dataset or N-Quads file twice into a store without deduplication; concurrent writers inserting the same quad; tests that insert fixtures then add them again; backfill jobs that are not idempotent.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


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