{"record":{"id":"68e3d9d1858af278","repo":"dgraph-io/dgraph","slug":"another-backup-operation-is-already-running","errorCode":null,"errorMessage":"another backup operation is already running","messagePattern":"another backup operation is already running","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"worker/draft.go","lineNumber":159,"sourceCode":"\t\tgo posting.IncrRollup.Process(closer, State.GetTimestamp)\n\tcase opRestore:\n\t\t// Restores cancel all other operations, except for other restores since\n\t\t// only one restore operation should be active any given moment.\n\t\tfor otherId, otherOp := range n.ops {\n\t\t\tif otherId == opRestore {\n\t\t\t\treturn nil, errors.Errorf(\"another restore operation is already running\")\n\t\t\t}\n\t\t\t// Remove from map and signal the closer to cancel the operation.\n\t\t\tdelete(n.ops, otherId)\n\t\t\totherOp.SignalAndWait()\n\t\t}\n\tcase opBackup:\n\t\t// Backup cancels all other operations, except for other backups since\n\t\t// only one backup operation should be active any given moment. Also, indexing at higher\n\t\t// timestamp can also run concurrently with backup.\n\t\tfor otherId, otherOp := range n.ops {\n\t\t\tif otherId == opBackup {\n\t\t\t\treturn nil, errors.Errorf(\"another backup operation is already running\")\n\t\t\t}\n\t\t\t// Remove from map and signal the closer to cancel the operation.\n\t\t\tdelete(n.ops, otherId)\n\t\t\totherOp.SignalAndWait()\n\t\t}\n\tcase opIndexing:\n\t\tfor otherId, otherOp := range n.ops {\n\t\t\tswitch otherId {\n\t\t\tcase opBackup:\n\t\t\t\tif otherOp.ts < ts {\n\t\t\t\t\t// If backup is running at higher timestamp, then indexing can't be executed.\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\treturn nil, errors.Errorf(\"operation %s is already running\", otherId)\n\t\t\tcase opRollup:\n\t\t\t\t// Remove from map and signal the closer to cancel the operation.\n\t\t\t\tdelete(n.ops, otherId)\n\t\t\t\totherOp.SignalAndWait()","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/worker/draft.go#L141-L177","documentation":"Raised in startTaskAtTs (worker/draft.go:159) when a backup is requested while another backup is already running. Backup cancels all other operation kinds but is not allowed to run concurrently with another backup.","triggerScenarios":"Calling startTask(opBackup) (POST /backup or backup gRPC) while a previous backup is still tracked in n.ops for the group.","commonSituations":"Overlapping scheduled backups (e.g. hourly cron on clusters where a backup takes longer than an hour); manual backup triggered while automated backup is running.","solutions":["Wait for the running backup to finish; check its status first.","Widen the backup schedule interval so it exceeds the longest observed backup duration.","Add a distributed lock / job queue so only one backup request is ever in flight.","Restart the node if a stale backup entry is blocking new backups."],"exampleFix":"// before\ncron.AddFunc(\"0 * * * *\", doBackup)\n// after: guard with in-flight check\nif !backupInFlight.Load() {\n    backupInFlight.Store(true)\n    defer backupInFlight.Store(false)\n    doBackup()\n}","handlingStrategy":"validation","validationCode":"if backupRunning(cluster) { return; }\nscheduleBackup()","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set backup cron interval > longest backup duration observed.","Track in-flight backups in an external state store.","Alert when a backup exceeds its expected window instead of stacking a new one."],"tags":["dgraph","backup","operation-conflict"],"backgroundTag":"operation-already-running","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}