{"record":{"id":"4874831a35c1a5cf","repo":"cayleygraph/cayley","slug":"errquadexists","errorCode":"ErrQuadExists","errorMessage":"quad exists","messagePattern":"quad exists","errorType":"error_code","errorClass":"DeltaError","httpStatus":null,"severity":"error","filePath":"graph/quadwriter.go","lineNumber":83,"sourceCode":"}\n\ntype Handle struct {\n\tQuadStore\n\tQuadWriter\n}\n\ntype IgnoreOpts struct {\n\tIgnoreDup, IgnoreMissing bool\n}\n\nfunc (h *Handle) Close() error {\n\terr := h.QuadWriter.Close()\n\th.QuadStore.Close()\n\treturn err\n}\n\nvar (\n\tErrQuadExists    = errors.New(\"quad exists\")\n\tErrQuadNotExist  = errors.New(\"quad does not exist\")\n\tErrInvalidAction = errors.New(\"invalid action\")\n\tErrNodeNotExists = errors.New(\"node does not exist\")\n)\n\n// DeltaError records an error and the delta that caused it.\ntype DeltaError struct {\n\tDelta Delta\n\tErr   error\n}\n\nfunc (e *DeltaError) Error() string {\n\tif !e.Delta.Quad.IsValid() {\n\t\treturn e.Err.Error()\n\t}\n\treturn e.Delta.Action.String() + \" \" + e.Delta.Quad.String() + \": \" + e.Err.Error()\n}\n","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/cayleygraph/cayley/blob/81dcd7d73e45136bc0d01802a8ba4685d8a533eb/graph/quadwriter.go#L65-L101","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check for existence first with qs.Quad exists/contains lookup before adding, or filter deltas through graph.NewRemover/Add logic","Skip or downgrade duplicates: pre-check each quad with a lookup and drop Add deltas for quads already stored","For gaedatastore, set ignoreOpts.IgnoreDup so duplicate adds are treated as no-ops","Compare errors with graph.IsQuadExist(err) and treat as success when duplicates are acceptable"],"exampleFix":"// before\nerr := qw.ApplyDeltas([]graph.Delta{{Action: graph.Add, Quad: q}})\n// after\nif !qs.QuadExists(q) { // or use graph.IsQuadExist(err) and ignore\n    err = qw.ApplyDeltas([]graph.Delta{{Action: graph.Add, Quad: q}})\n}","handlingStrategy":"try-catch","validationCode":"// pre-check before adding\nif qs.QuadExists(quad) {\n    return nil // skip duplicate\n}\nreturn qw.ApplyDeltas([]graph.Delta{{Action: graph.Add, Quad: quad}})","typeGuard":"func isQuadExists(err error) bool { return errors.Is(err, graph.ErrQuadExists) || graph.IsQuadExist(err) }","tryCatchPattern":"err := qw.ApplyDeltas(deltas)\nif err != nil {\n    if graph.IsQuadExist(err) {\n        // duplicate add: safe to ignore or log\n    } else {\n        return err\n    }\n}","preventionTips":["Make ingestion idempotent by pre-checking quad existence","Enable IgnoreDup options when replaying datasets","Deduplicate delta batches before submission","Use graph.IsQuadExist to classify duplicates explicitly"],"tags":["graph","quadstore","duplicate","delta"],"backgroundTag":"file-already-exists","analyzedSha":"81dcd7d73e45136bc0d01802a8ba4685d8a533eb","analyzedAt":"2026-09-06T06:14:12.358Z","contentChangedAt":"2026-09-06T06:14:12.358Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}