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

  1. Look the node up in the quadstore first (qs.NameOf / qs.ValueOf) and skip removal if nil
  2. Treat the error as success for idempotent cleanup by comparing with graph.ErrNodeNotExists / errors.Is
  3. Re-check that the node ID spelling matches the store's identifiers (case, namespace, IRI vs BNode)
  4. 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

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.