cayleygraph/cayley · error · DeltaError
ErrNodeNotExists
ErrNodeNotExists
Error message
node does not exist
What it means
ErrNodeNotExists is returned by NodeRemover implementations (writer/single.go RemoveNode) when the node value to be removed does not exist in the quadstore: either the value lookup returns nil or the node has zero quads attached. No deltas are applied in that case.
Source
Thrown at graph/quadwriter.go:86
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 {
return e.Err
}View on GitHub (pinned to 81dcd7d73e)
Solutions
- Look the node up in the quadstore first (qs.NameOf / qs.ValueOf) and skip removal if nil
- Treat the error as success for idempotent cleanup by comparing with graph.ErrNodeNotExists / errors.Is
- Re-check that the node ID spelling matches the store's identifiers (case, namespace, IRI vs BNode)
- If the node was deleted concurrently, re-query and continue the batch instead of aborting
Example fix
// before
err := graph.RemoveNodeAndAllRefs(qs, val)
// after
if qs.NameOf(val) != nil {
err = graph.RemoveNodeAndAllRefs(qs, val)
if err != nil && !errors.Is(err, graph.ErrNodeNotExists) {
return err
}
} Defensive patterns
Strategy: validation
Validate before calling
if qs.NameOf(val) == nil {
return nil // node absent; nothing to remove
} Type guard
func nodeExists(qs graph.QuadStore, v graph.Value) bool { return v != nil && qs.NameOf(v) != nil } Try / catch
err := graph.RemoveNodeAndAllRefs(qs, val)
if err != nil {
if errors.Is(err, graph.ErrNodeNotExists) {
return nil // idempotent remove
}
return err
} Prevention
- Resolve node identifiers through the store before removal
- Make node-cleanup routines idempotent by ignoring ErrNodeNotExists
- Normalize node IDs (IRI vs BNode, case) before lookup
- Re-query node state instead of trusting external ID lists
When it happens
Trigger: Calling RemoveNode(qs, val) for a Value that is not present in the store (lookup returns nil); calling RemoveNodeAndAllRefs/RemoveNode when total quad count for the node is 0; removing a node that was already deleted or never inserted.
Common situations: Cleanup jobs removing nodes by IDs from external data where the node was never imported; double-invocation of a removal routine; deleting nodes referenced by stale identifiers after a reindex or migration.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
AI-assisted analysis of cayleygraph/cayley@81dcd7d73e (2026-09-06).
Data as JSON: /api/errors/983e2b61438e151d.
Report an issue: GitHub.