{"record":{"id":"fd63f1da6e92f3de","repo":"dgraph-io/dgraph","slug":"transaction-is-too-old","errorCode":null,"errorMessage":"Transaction is too old","messagePattern":"Transaction is too old","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"posting/mvcc.go","lineNumber":62,"sourceCode":"\tpriorityKeys []*pooledKeys\n\tcount        uint64\n\n\t// Get Timestamp function gets a new timestamp to store the rollup at. This makes sure that\n\t// we are not overwriting any transaction. If there are transactions that are ongoing,\n\t// which modify the item, rollup wouldn't affect the data, as a delta would be written\n\t// later on\n\tgetNewTs func(bool) uint64\n\tcloser   *z.Closer\n}\n\ntype CachePL struct {\n\tlist       *List\n\tlastUpdate uint64\n}\n\nvar (\n\t// ErrTsTooOld is returned when a transaction is too old to be applied.\n\tErrTsTooOld = errors.Errorf(\"Transaction is too old\")\n\t// ErrInvalidKey is returned when trying to read a posting list using\n\t// an invalid key (e.g the key to a single part of a larger multi-part list).\n\tErrInvalidKey = errors.Errorf(\"cannot read posting list using multi-part list key\")\n\t// ErrHighPriorityOp is returned when rollup is cancelled so that operations could start.\n\tErrHighPriorityOp = errors.New(\"Cancelled rollup to make way for high priority operation\")\n\n\t// IncrRollup is used to batch keys for rollup incrementally.\n\tIncrRollup = &incrRollupi{\n\t\tpriorityKeys: make([]*pooledKeys, 2),\n\t}\n)\n\nvar MemLayerInstance *MemoryLayer\n\nfunc init() {\n\tx.AssertTrue(len(IncrRollup.priorityKeys) == 2)\n\tfor i := range IncrRollup.priorityKeys {\n\t\tIncrRollup.priorityKeys[i] = &pooledKeys{","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/posting/mvcc.go#L44-L80","documentation":"ErrTsTooOld is returned when a mutation arrives with a start timestamp older than the current watermark/commit state, meaning the transaction is so old its mutations can no longer be safely applied in the MVCC ordering. The transaction must be aborted and retried with a fresh timestamp.","triggerScenarios":"addMutationHelper / addReverseMutationHelper receive a txn whose startTs is less than or equal to a committed watermark (e.g. after the txn was delayed in a queue, or a client held a read-only/low-timestamp transaction too long while writes committed).","commonSituations":"Long-lived transactions held open by a client for minutes/hours while other writers commit; heavy write load starving a queued transaction; clock/timestamp skew after cluster membership or snapshot changes.","solutions":["Abort the transaction and retry it with a new timestamp (client retry loop)","Keep transactions short-lived; avoid holding mutations open during slow app logic","Reduce write contention causing mutation queues to back up past the watermark","Verify Alpha timestamps/watermarks are advancing normally (no stalled oracle)"],"exampleFix":"// before\nerr := dgraphMutate(ctx, txn) // txn started long ago\n// after: retry on ErrTsTooOld\nerr := dgraphMutate(ctx, txn)\nif errors.Is(err, posting.ErrTsTooOld) {\n    txn = startFreshTxn(ctx)\n    err = dgraphMutate(ctx, txn)\n}","handlingStrategy":"retry","validationCode":"// Before mutating, ensure the txn's startTs is still valid (app-level check)\nif time.Since(txnStartedAt) > maxTxnAge {\n    txn = restartTxn(ctx) // abort and start a fresh transaction\n}","typeGuard":null,"tryCatchPattern":"err := runMutation(ctx, txn)\nif errors.Is(err, posting.ErrTsTooOld) {\n    txn.Discard()\n    txn = dgraph.NewTxn(ctx)\n    err = runMutation(ctx, txn) // retry with fresh timestamp\n}","preventionTips":["Keep transactions short; commit promptly after reads","Never hold a write transaction across user input or long computation","Retry on ErrTsTooOld at the client with backoff","Monitor alpha mutation queue depth and watermark lag"],"tags":["mvcc","timestamp","conflict"],"backgroundTag":"transaction-too-old","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}