{"record":{"id":"4f191e863541270c","repo":"dgraph-io/dgraph","slug":"pending-transactions-found-please-retry-operation","errorCode":null,"errorMessage":"Pending transactions found. Please retry operation","messagePattern":"Pending transactions found\\. Please retry operation","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"worker/draft.go","lineNumber":310,"sourceCode":"\tvar cc raftpb.ConfChange\n\tif err := cc.Unmarshal(e.Data); err != nil {\n\t\tglog.Errorf(\"While unmarshalling confchange: %+v\", err)\n\t}\n\n\tif cc.Type == raftpb.ConfChangeRemoveNode {\n\t\tn.DeletePeer(cc.NodeID)\n\t} else if len(cc.Context) > 0 {\n\t\tvar rc pb.RaftContext\n\t\tx.Check(proto.Unmarshal(cc.Context, &rc))\n\t\tn.Connect(rc.Id, rc.Addr)\n\t}\n\n\tcs := n.Raft().ApplyConfChange(cc)\n\tn.SetConfState(cs)\n\tn.DoneConfChange(cc.ID, nil)\n}\n\nvar errHasPendingTxns = errors.New(\"Pending transactions found. Please retry operation\")\n\n// We must not wait here. Previously, we used to block until we have aborted the\n// transactions. We're now applying all updates serially, so blocking for one\n// operation is not an option.\nfunc detectPendingTxns(attr string) error {\n\ttctxs := posting.Oracle().IterateTxns(func(key []byte) bool {\n\t\tpk, err := x.Parse(key)\n\t\tif err != nil {\n\t\t\tglog.Errorf(\"error %v while parsing key %v\", err, hex.EncodeToString(key))\n\t\t\treturn false\n\t\t}\n\t\treturn pk.Attr == attr\n\t})\n\tif len(tctxs) == 0 {\n\t\treturn nil\n\t}\n\tgo tryAbortTransactions(tctxs)\n\treturn errHasPendingTxns","sourceCodeStart":292,"sourceCodeEnd":328,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/worker/draft.go#L292-L328","documentation":"errHasPendingTxns, returned by detectPendingTxns (worker/draft.go:310). Mutating operations (drop all, restore start) applied through Raft abort when there are still pending (uncommitted or un-aborted) transactions at the time the proposal applies. The client is told to retry once those transactions have been aborted/finished.","triggerScenarios":"Running DropAll/DropData or a restore while another transaction holds watermarks: posting.Oracle().IterateTxns finds non-empty pending transaction contexts at apply time.","commonSituations":"Dropping all data while queries/writes are in flight; starting a restore while open transactions exist; heavy write load during maintenance operations.","solutions":["Retry the operation after a short backoff — the message explicitly says to retry; pending txns get aborted automatically.","Pause application writes/queries during drop-all or restore to prevent new pending transactions.","If it persists, restart the node to clear stuck transaction state and retry.","Investigate long-running transactions holding the oracle watermark."],"exampleFix":"// before: one-shot drop that can fail\nclient.DropAll()\n// after: retry on pending-txn error\nfor i := 0; i < 5; i++ {\n    err := client.DropAll()\n    if err == nil || !strings.Contains(err.Error(), \"Pending transactions\") { break }\n    time.Sleep(time.Duration(1<<i) * time.Second)\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"for i := 0; i < 5; i++ {\n    err := client.DropAll()\n    if err == nil || !strings.Contains(err.Error(), \"Pending transactions\") {\n        return err\n    }\n    time.Sleep(time.Duration(1<<i) * time.Second)\n}\nreturn errors.New(\"drop-all kept failing: pending txns\")","preventionTips":["Quiesce client traffic before drop-all/restore operations.","Add exponential-backoff retries keyed on this error string.","Investigate transactions stuck open for long durations.","Schedule maintenance drops in low-write windows."],"tags":["dgraph","transactions","drop-all","restore"],"backgroundTag":"pending-transactions-conflict","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}