gastownhall/beads · error

compare local HEAD to %s: %w

Error message

compare local HEAD to %s: %w

What it means

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.

Source

Thrown at internal/storage/versioncontrolops/fastforward.go:46

		return false, fmt.Errorf("invalid ref: %w", err)
	}

	// Dolt's AS OF requires a literal ref, not a bind parameter; ref was
	// validated above via the shared allowlist regex, mirroring the same
	// ahead/behind pattern used by EmbeddedDoltStore.SyncStatus
	// (internal/storage/embeddeddolt/federation.go).
	//nolint:gosec // G201: ref validated by ValidateRef above — AS OF requires a literal
	query := fmt.Sprintf(`
		SELECT
			(SELECT COUNT(*) FROM dolt_log WHERE commit_hash NOT IN
				(SELECT commit_hash FROM dolt_log AS OF '%s')) AS ahead,
			(SELECT COUNT(*) FROM dolt_log AS OF '%s' WHERE commit_hash NOT IN
				(SELECT commit_hash FROM dolt_log)) AS behind
	`, ref, ref)

	var ahead, behind int
	if err := db.QueryRowContext(ctx, query).Scan(&ahead, &behind); err != nil {
		return false, fmt.Errorf("compare local HEAD to %s: %w", ref, err)
	}

	return ahead == 0 && behind >= 1, nil
}

// WorkingSetClean reports whether the Dolt working set has no uncommitted
// changes, EXCLUDING dolt-ignored wisp tables ("wisps" and "wisp_*"), which
// cannot be staged/committed and so should never block a clean-working-set
// gate. This mirrors the exclusion in DirtyTableTracker.MarkDirty
// (commit.go), but — unlike the unexported workingSetClean in
// mergesettle.go, which does not exclude wisps and swallows its query
// error — this reports the error to the caller instead of treating it as
// dirty.
func WorkingSetClean(ctx context.Context, db DBConn) (bool, error) {
	rows, err := db.QueryContext(ctx, "SELECT table_name FROM dolt_status")
	if err != nil {
		return false, fmt.Errorf("query dolt_status: %w", err)
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. 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.
  2. Run CALL DOLT_FETCH('origin') or the repo's sync step, then retry.
  3. Check the underlying wrapped error: sql.ErrNoRows/context.DeadlineExceeded indicate DB or context issues, not a ref problem.
  4. Confirm the Dolt server/embedded engine is running and dolt_log is queryable.

Example fix

// before
ok, err := versioncontrolops.LocalIsStrictAncestorOf(ctx, db, "origin/main")
// after
if err := fetchRemoteRefs(ctx); err != nil { // ensures origin/* refs are cached
    return err
}
ok, err := versioncontrolops.LocalIsStrictAncestorOf(ctx, db, "origin/main")
Defensive patterns

Strategy: try-catch

Validate before calling

var exists int
err := db.QueryRowContext(ctx,
    "SELECT COUNT(*) FROM dolt_branch WHERE name = ?", ref).Scan(&exists)
if err != nil || exists == 0 {
    return fmt.Errorf("ref %q not cached locally; fetch first", ref)
}

Try / catch

ok, err := versioncontrolops.LocalIsStrictAncestorOf(ctx, db, ref)
if err != nil {
    if errors.Is(err, context.DeadlineExceeded) {
        return retryWithNewDeadline(ctx)
    }
    return fmt.Errorf("ancestor check for %s failed: %w", ref, err)
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/729c53c1693f9dad. Report an issue: GitHub.