{"record":{"id":"78a938cebd7d0b2f","repo":"dgraph-io/dgraph","slug":"while-proposing","errorCode":null,"errorMessage":"While proposing","messagePattern":"While proposing","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"worker/proposal.go","lineNumber":238,"sourceCode":"\t\t// We don't need to extend from base ctx as it might have a timeout. This timeout\n\t\t// is only to find the proposal back via Raft.\n\t\tcctx, cancel := context.WithCancel(context.Background())\n\t\tdefer cancel()\n\n\t\terrCh := make(chan error, 1)\n\t\tpctx := &conn.ProposalCtx{\n\t\t\tErrCh: errCh,\n\t\t\tCtx:   cctx,\n\t\t}\n\t\tx.AssertTruef(n.Proposals.Store(key, pctx), \"Found existing proposal with key: [%x]\", key)\n\t\tdefer n.Proposals.Delete(key) // Ensure that it gets deleted on return.\n\n\t\tspan.AddEvent(\"Proposing\", trace.WithAttributes(\n\t\t\tattribute.Int64(\"key\", int64(key)),\n\t\t\tattribute.String(\"timeout\", timeout.String())))\n\n\t\tif err = n.Raft().Propose(cctx, data); err != nil {\n\t\t\treturn errors.Wrapf(err, \"While proposing\")\n\t\t}\n\n\t\ttimer := time.NewTimer(timeout)\n\n\t\tfor {\n\t\t\tselect {\n\t\t\tcase err = <-errCh:\n\t\t\t\t// We arrived here by a call to n.Proposals.Done().\n\t\t\t\treturn err\n\t\t\tcase <-ctx.Done():\n\t\t\t\tglog.Warningf(\"Context expired while processing proposal %v\", ctx.Err())\n\t\t\t\treturn ctx.Err()\n\t\t\tcase <-timer.C:\n\t\t\t\tif atomic.LoadUint32(&pctx.Found) > 0 {\n\t\t\t\t\t// We found the proposal in CommittedEntries. No need to retry.\n\t\t\t\t} else {\n\t\t\t\t\tspan.AddEvent(\"Timeout reached\", trace.WithAttributes(\n\t\t\t\t\t\tattribute.String(\"timeout\", timeout.String())))","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/worker/proposal.go#L220-L256","documentation":"This error wraps a failure returned by the Raft Raft().Propose() call (pkg/errors.Wrapf), meaning a proposal (e.g. a mutation) could not be submitted to the Raft group within the given timeout. It is thrown in the proposal path in worker/proposal.go after a tracing 'Proposing' event, so the underlying cause is whatever Propose returned (leadership loss, deadline exceeded, shard unavailable).","triggerScenarios":"Calling n.Raft().Propose(cctx, data) with a context that times out or is cancelled before the proposal is committed; losing Raft leadership mid-proposal; the Raft group being unavailable (quorum lost, node restarting).","commonSituations":"Heavy write load or slow disks making Raft commits exceed the proposal timeout; an Alpha that was just demoted from leader still serving mutations; network partitions between Alpha nodes; client set a short mutation timeout.","solutions":["Retry the mutation — if this node lost leadership, a new leader will accept the proposal","Increase the client-side mutation/operation timeout and retry with backoff","Check Raft group health (leader elections in logs, /health endpoint) and ensure quorum of Alphas is up","Inspect the wrapped cause with errors.Cause()/Unwrap to address the root error"],"exampleFix":"// before\nerr := n.Raft().Propose(ctx, data)\nif err != nil { return err }\n// after\nerr := n.Raft().Propose(ctx, data)\nif err != nil {\n    if isLeadershipOrTimeout(err) {\n        time.Sleep(backoff)\n        err = n.Raft().Propose(ctx, data)\n    }\n    return err\n}","handlingStrategy":"retry","validationCode":"// Prefer a healthy, leader-connected client before proposing\nif !client.Healthy(ctx) {\n    return fmt.Errorf(\"alpha unreachable; pick another client\")\n}\nctx, cancel := context.WithTimeout(ctx, 30*time.Second)\ndefer cancel()","typeGuard":null,"tryCatchPattern":"err := propose(ctx, data)\nvar netErr net.Error\nif errors.As(err, &netErr) || isContextDeadline(err) || isNotLeader(err) {\n    time.Sleep(backoff)\n    err = propose(ctx, data)\n}\nif err != nil {\n    log.Printf(\"proposal failed: %v\", err)\n}","preventionTips":["Always set a generous explicit timeout on the proposal context","Retry idempotent proposals after leadership changes","Monitor Raft leader elections and quorum health","Check the wrapped root cause (errors.Unwrap) before blaming the proposal itself"],"tags":["raft","distributed-systems","timeout","dgraph"],"backgroundTag":"raft-proposal-failed","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}