{"record":{"id":"7be5cd877a28a368","repo":"cayleygraph/cayley","slug":"nothing-to-log","errorCode":null,"errorMessage":"Nothing to log","messagePattern":"Nothing to log","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"graph/gaedatastore/quadstore.go","lineNumber":408,"sourceCode":"\t\t}\n\t\tfoundMetadata.QuadCount += quadsAdded\n\t\tfoundMetadata.NodeCount += nodesAdded\n\t\t_, err = datastore.Put(c, key, foundMetadata)\n\t\tif err != nil {\n\t\t\tclog.Errorf(\"Error: %v\", err)\n\t\t}\n\t\treturn err\n\t}, nil)\n\treturn err\n}\n\nfunc (qs *QuadStore) updateLog(in []graph.Delta) ([]int64, error) {\n\tif qs.context == nil {\n\t\terr := errors.New(\"Error updating log, context is nil, graph not correctly initialised\")\n\t\treturn nil, err\n\t}\n\tif len(in) == 0 {\n\t\treturn nil, errors.New(\"Nothing to log\")\n\t}\n\tlogEntries := make([]LogEntry, 0, len(in))\n\tlogKeys := make([]*datastore.Key, 0, len(in))\n\tfor _, d := range in {\n\t\tvar action string\n\t\tif d.Action == graph.Add {\n\t\t\taction = \"Add\"\n\t\t} else {\n\t\t\taction = \"Delete\"\n\t\t}\n\n\t\tentry := LogEntry{\n\t\t\tAction:    action,\n\t\t\tKey:       qs.createKeyForQuad(d.Quad).String(),\n\t\t\tTimestamp: time.Now().UnixNano(),\n\t\t}\n\t\tlogEntries = append(logEntries, entry)\n\t\tlogKeys = append(logKeys, qs.createKeyForLog())","sourceCodeStart":390,"sourceCodeEnd":426,"githubUrl":"https://github.com/cayleygraph/cayley/blob/81dcd7d73e45136bc0d01802a8ba4685d8a533eb/graph/gaedatastore/quadstore.go#L390-L426","documentation":"updateLog returns this when the caller passes an empty delta slice — there are no operations to record in the datastore log. It is a guard against writing an empty LogEntry batch.","triggerScenarios":"Calling updateLog directly with in == nil or len(in) == 0; ApplyDeltas reaching updateLog with a batch that filtered down to nothing (e.g. all deltas dropped by ignoreOpts handling).","commonSituations":"Calling ApplyDeltas with an empty slice; batch-assembly code appending no deltas but still invoking the write path; refactoring that split ApplyDeltas and lost the empty-check upstream.","solutions":["Check len(deltas) > 0 before calling ApplyDeltas/updateLog.","Return early in your write path when the batch is empty instead of calling into the store.","If all deltas were intentionally ignored, treat this as a no-op rather than an error in your caller.","Inspect upstream ignoreOpts logic if a non-empty batch shrinks to zero."],"exampleFix":"// before\nqs.updateLog(nil)\n// after\nif len(deltas) == 0 { return nil }\nqs.updateLog(deltas)","handlingStrategy":"validation","validationCode":"if len(deltas) == 0 {\n    return nil // nothing to do\n}\nreturn qs.updateLog(deltas)","typeGuard":null,"tryCatchPattern":"if err := qs.ApplyDeltas(deltas, ignoreOpts); err != nil {\n    if strings.Contains(err.Error(), \"Nothing to log\") {\n        return nil // treat empty batch as no-op\n    }\n    return err\n}","preventionTips":["Check len(batch) > 0 before calling write APIs.","Treat empty batches as legitimate no-ops upstream.","Review ignoreOpts logic that can empty a batch."],"tags":["datastore","logging","empty-input"],"backgroundTag":"empty-required-field","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"}