{"record":{"id":"729c53c1693f9dad","repo":"gastownhall/beads","slug":"compare-local-head-to-s-w","errorCode":null,"errorMessage":"compare local HEAD to %s: %w","messagePattern":"compare local HEAD to (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/versioncontrolops/fastforward.go","lineNumber":46,"sourceCode":"\t\treturn false, fmt.Errorf(\"invalid ref: %w\", err)\n\t}\n\n\t// Dolt's AS OF requires a literal ref, not a bind parameter; ref was\n\t// validated above via the shared allowlist regex, mirroring the same\n\t// ahead/behind pattern used by EmbeddedDoltStore.SyncStatus\n\t// (internal/storage/embeddeddolt/federation.go).\n\t//nolint:gosec // G201: ref validated by ValidateRef above — AS OF requires a literal\n\tquery := fmt.Sprintf(`\n\t\tSELECT\n\t\t\t(SELECT COUNT(*) FROM dolt_log WHERE commit_hash NOT IN\n\t\t\t\t(SELECT commit_hash FROM dolt_log AS OF '%s')) AS ahead,\n\t\t\t(SELECT COUNT(*) FROM dolt_log AS OF '%s' WHERE commit_hash NOT IN\n\t\t\t\t(SELECT commit_hash FROM dolt_log)) AS behind\n\t`, ref, ref)\n\n\tvar ahead, behind int\n\tif err := db.QueryRowContext(ctx, query).Scan(&ahead, &behind); err != nil {\n\t\treturn false, fmt.Errorf(\"compare local HEAD to %s: %w\", ref, err)\n\t}\n\n\treturn ahead == 0 && behind >= 1, nil\n}\n\n// WorkingSetClean reports whether the Dolt working set has no uncommitted\n// changes, EXCLUDING dolt-ignored wisp tables (\"wisps\" and \"wisp_*\"), which\n// cannot be staged/committed and so should never block a clean-working-set\n// gate. This mirrors the exclusion in DirtyTableTracker.MarkDirty\n// (commit.go), but — unlike the unexported workingSetClean in\n// mergesettle.go, which does not exclude wisps and swallows its query\n// error — this reports the error to the caller instead of treating it as\n// dirty.\nfunc WorkingSetClean(ctx context.Context, db DBConn) (bool, error) {\n\trows, err := db.QueryContext(ctx, \"SELECT table_name FROM dolt_status\")\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"query dolt_status: %w\", err)\n\t}","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/versioncontrolops/fastforward.go#L28-L64","documentation":"After validating the ref, LocalIsStrictAncestorOf runs a dolt_log AS OF query comparing the ref's history to local HEAD. If db.QueryRowContext or the row Scan fails (connection error, unknown ref/table error from Dolt, context cancellation), the error is wrapped as \"compare local HEAD to <ref>: %w\" and the function returns false.","triggerScenarios":"Querying with a ref that passes syntax validation but does not exist in the database (AS OF 'origin/main' when that ref was never fetched); a closed/failed DB connection; the context being cancelled mid-query; dolt_log being unreadable.","commonSituations":"Calling before any fetch so the remote-tracking ref is absent; typo'd branch name like 'orgin/main'; network/database outage while the embedded Dolt engine is unavailable; operation cancelled by a deadline.","solutions":["Verify the ref exists locally (it must be a cached remote-tracking ref, e.g. after a fetch) — the function performs no fetch of its own.","Run CALL DOLT_FETCH('origin') or the repo's sync step, then retry.","Check the underlying wrapped error: sql.ErrNoRows/context.DeadlineExceeded indicate DB or context issues, not a ref problem.","Confirm the Dolt server/embedded engine is running and dolt_log is queryable."],"exampleFix":"// before\nok, err := versioncontrolops.LocalIsStrictAncestorOf(ctx, db, \"origin/main\")\n// after\nif err := fetchRemoteRefs(ctx); err != nil { // ensures origin/* refs are cached\n    return err\n}\nok, err := versioncontrolops.LocalIsStrictAncestorOf(ctx, db, \"origin/main\")","handlingStrategy":"try-catch","validationCode":"var exists int\nerr := db.QueryRowContext(ctx,\n    \"SELECT COUNT(*) FROM dolt_branch WHERE name = ?\", ref).Scan(&exists)\nif err != nil || exists == 0 {\n    return fmt.Errorf(\"ref %q not cached locally; fetch first\", ref)\n}","typeGuard":null,"tryCatchPattern":"ok, err := versioncontrolops.LocalIsStrictAncestorOf(ctx, db, ref)\nif err != nil {\n    if errors.Is(err, context.DeadlineExceeded) {\n        return retryWithNewDeadline(ctx)\n    }\n    return fmt.Errorf(\"ancestor check for %s failed: %w\", ref, err)\n}","preventionTips":["Fetch remote refs before any ancestor check — the function performs no fetch of its own.","Wrap calls with a reasonable context timeout so transient DB hangs don't stall callers.","Verify ref spelling against `CALL DOLT_BRANCH()` output when debugging."],"tags":["dolt","sql","database","query-error"],"backgroundTag":"unknown-dolt-ref","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}