{"record":{"id":"950226b1f233b4ee","repo":"cayleygraph/cayley","slug":"error-cleaning-up-nodes-v","errorCode":null,"errorMessage":"error cleaning up nodes: %v","messagePattern":"error cleaning up nodes: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"graph/nosql/quadstore.go","lineNumber":261,"sourceCode":"\tif inc == 0 {\n\t\treturn nil\n\t}\n\td := toDocumentValue(&qs.opt, name)\n\terr := qs.db.Update(colNodes, key).Upsert(d).Inc(fldSize, inc).Do(ctx)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error updating node: %v\", err)\n\t}\n\treturn nil\n}\n\nfunc (qs *QuadStore) cleanupNodes(ctx context.Context, keys []nosql.Key) error {\n\terr := qs.db.Delete(colNodes).Keys(keys...).WithFields(nosql.FieldFilter{\n\t\tPath:   []string{fldSize},\n\t\tFilter: nosql.Equal,\n\t\tValue:  nosql.Int(0),\n\t}).Do(ctx)\n\tif err != nil {\n\t\terr = fmt.Errorf(\"error cleaning up nodes: %v\", err)\n\t}\n\treturn err\n}\n\nfunc (qs *QuadStore) updateQuad(ctx context.Context, q quad.Quad, proc graph.Procedure) error {\n\tvar setname string\n\tif proc == graph.Add {\n\t\tsetname = fldQuadAdded\n\t} else if proc == graph.Delete {\n\t\tsetname = fldQuadDeleted\n\t}\n\tdoc := nosql.Document{\n\t\tfldSubject:   nosql.String(hashOf(q.Subject)),\n\t\tfldPredicate: nosql.String(hashOf(q.Predicate)),\n\t\tfldObject:    nosql.String(hashOf(q.Object)),\n\t}\n\tif l := hashOf(q.Label); l != \"\" {\n\t\tdoc[fldLabel] = nosql.String(l)","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/cayleygraph/cayley/blob/81dcd7d73e45136bc0d01802a8ba4685d8a533eb/graph/nosql/quadstore.go#L243-L279","documentation":"Returned by QuadStore.cleanupNodes when the conditional Delete on the nodes collection fails. After applying deltas, nodes whose fldSize dropped to 0 are deleted via a field filter (Path fldSize == nosql.Int(0)); this error wraps the driver error from that Delete(...).Do(ctx) call.","triggerScenarios":"Applying deltas that remove the last reference to a node while the NoSQL backend fails the filtered delete: connection loss, ctx cancellation, driver not supporting the Equal field filter, or a backend that rejects conditional deletes.","commonSituations":"NoSQL driver lacking field-filter delete support (some backends only support key deletes); network drop during ApplyDeltas cleanup phase; MongoDB authentication/authorization lacking delete permission on the collection.","solutions":["Read the wrapped driver error; fix database connectivity/permissions first.","Ensure the DB user has delete privileges on the nodes collection.","Confirm the chosen NoSQL backend supports filtered (WithFields/Equal) deletes; if not, switch backend or upgrade the driver integration.","Increase the context timeout and retry the delta application.","If deletes keep failing, nodes with size 0 are only cosmetic garbage — you can run the cleanup manually later, but fix the root cause."],"exampleFix":"// before\nif err != nil {\n    err = fmt.Errorf(\"error cleaning up nodes: %v\", err)\n}\n// after\nif err != nil {\n    return fmt.Errorf(\"error cleaning up nodes: %w\", err) // inspect the cause\n}\n// caller side: use a longer-lived context for batch cleanup\nctx, cancel := context.WithTimeout(context.Background(), time.Minute)\ndefer cancel()","handlingStrategy":"try-catch","validationCode":"// check DB privileges/connectivity before delta application\nif err := dbPing(ctx, spec); err != nil {\n    return fmt.Errorf(","typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":["database","nosql","delete-failed","cayley"],"backgroundTag":"database-write-failed","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"}