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.

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.

Appendix: 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)