{"record":{"id":"54926741470a24bf","repo":"gastownhall/beads","slug":"pull-succeeded-but-is-blocked-recompute-failed-w-549267","errorCode":null,"errorMessage":"pull succeeded but is_blocked recompute failed: %w","messagePattern":"pull succeeded but is_blocked recompute failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dolt/store.go","lineNumber":4032,"sourceCode":"\t\tpreHead = h\n\t}\n\n\tif err := s.pullTransport(ctx, remote); err != nil {\n\t\treturn err\n\t}\n\n\t// ga-ivaps: a route that returns nil having merged nothing is silent\n\t// divergence, so a transport's own \"success\" is not taken as proof the\n\t// merge landed. Checked before the recompute: recomputing derived state\n\t// over a merge that never arrived would report a second success on top of\n\t// the first.\n\tif err := s.verifyPullLanded(ctx, remote, preHead); err != nil {\n\t\treturn err\n\t}\n\n\tif !s.readOnly {\n\t\tif err := s.recomputeBlockedAfterPull(ctx, preHead); err != nil {\n\t\t\treturn fmt.Errorf(\"pull succeeded but is_blocked recompute failed: %w\", err)\n\t\t}\n\t}\n\treturn nil\n}\n\n// branchHash returns the commit hash at the tip of a local branch, or the empty\n// string when the branch has no row. Reads dolt_branches, which is global to the\n// database, so the answer does not depend on which branch the pooled connection\n// happens to be sitting on.\nfunc (s *DoltStore) branchHash(ctx context.Context, branch string) (string, error) {\n\tvar hash string\n\tif err := s.db.QueryRowContext(ctx, \"SELECT hash FROM dolt_branches WHERE name = ?\", branch).Scan(&hash); err != nil {\n\t\tif errors.Is(err, sql.ErrNoRows) {\n\t\t\treturn \"\", nil\n\t\t}\n\t\treturn \"\", err\n\t}\n\treturn hash, nil","sourceCodeStart":4014,"sourceCodeEnd":4050,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dolt/store.go#L4014-L4050","documentation":"After a successful pull, a writable store recomputes the denormalized is_blocked column for rows the merge touched. This error is raised when the pull itself landed fine but that post-merge recompute failed. The data is merged but derived dependency state may be stale or inconsistent until the recompute succeeds.","triggerScenarios":"Pull()/PullRemote() on a writable store where recomputeBlockedAfterPull fails after verifyPullLanded succeeded: the recompute UPDATE/dependency-walk errors out (connection timeout, context deadline, SQL error) against s.db.","commonSituations":"Large merges touching many dependent issues exceed the pool's ~10s read timeout; the context was cancelled mid-recompute; a trigger or constraint rejects the is_blocked UPDATE; the sql-server was restarted between the merge and the recompute.","solutions":["Read the wrapped cause to see whether it was a timeout, cancellation, or SQL error.","Re-run the pull or a recompute pass — the merge already landed, so a retry of the pull is a no-op and the recompute will run again.","Increase the query timeout or shrink the batch size if the recompute is timing out on big merges.","If is_blocked values look wrong afterward, run the store's recompute/repair path manually.","Check sql-server health if the cause was a connection failure."],"exampleFix":"// before\nerr := store.Pull(ctx)\n// after\nif err != nil && strings.Contains(err.Error(), \"is_blocked recompute failed\") {\n    // merge landed; only derived state is stale — re-pull to retrigger recompute\n    err = store.Pull(ctx)\n}","handlingStrategy":"retry","validationCode":"if err := ctx.Err(); err != nil { return err } // ensure context is live before pulling","typeGuard":null,"tryCatchPattern":"if err := store.Pull(ctx); err != nil {\n    if strings.Contains(err.Error(), \"is_blocked recompute failed\") {\n        // merge already landed; re-pull to retrigger only the recompute\n        return store.Pull(ctx)\n    }\n    return err\n}","preventionTips":["Use generous context timeouts for pulls of large dependency graphs.","Verify is_blocked values after big merges if you consume them directly.","Keep the sql-server healthy so recompute queries don't drop.","Watch for repeated recompute failures — investigate the wrapped SQL error rather than blind-retrying."],"tags":["dolt","pull","recompute","data-consistency"],"backgroundTag":"post-merge-recompute-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}