gastownhall/beads · error
delete remote-tracking ref %s: %w
Error message
delete remote-tracking ref %s: %w
What it means
PruneRemoteRefs deletes each cached remote-tracking ref via CALL DOLT_BRANCH('-D', '-r', name). This error wraps a failure of that stored-procedure call for a specific ref, with the ref name embedded in the message. It reports which ref could not be deleted; the returned slice contains the refs already deleted before the failure.
Source
Thrown at internal/storage/versioncontrolops/remoterefs.go:44
}
// PruneRemoteRefs deletes every cached remote-tracking ref and returns the
// names deleted. After a history squash (Flatten/Compact) these refs still
// anchor the pre-squash commit chain, so DOLT_GC treats the entire old history
// as reachable and reclaims nothing (bd-agctw). Pruning is safe on a squashed
// workspace: the refs are local caches only — nothing is deleted on the remote
// itself — and the next push or fetch re-creates them at the new tip.
//
// On error, the returned slice holds the refs deleted before the failure.
func PruneRemoteRefs(ctx context.Context, db DBConn) ([]string, error) {
refs, err := ListRemoteRefs(ctx, db)
if err != nil {
return nil, err
}
var pruned []string
for _, name := range refs {
if _, err := db.ExecContext(ctx, "CALL DOLT_BRANCH('-D', '-r', ?)", name); err != nil {
return pruned, fmt.Errorf("delete remote-tracking ref %s: %w", name, err)
}
pruned = append(pruned, name)
}
return pruned, nil
}
// ListTags returns the names of all Dolt tags, sorted by name. Tags anchor
// history the same way remote-tracking refs do, but they are user-created, so
// callers should surface them rather than delete them.
func ListTags(ctx context.Context, db DBConn) ([]string, error) {
rows, err := db.QueryContext(ctx, "SELECT tag_name FROM dolt_tags ORDER BY tag_name")
if err != nil {
return nil, fmt.Errorf("list tags: %w", err)
}
defer rows.Close()
var tags []string
for rows.Next() {View on GitHub (pinned to 71377f2769)
Solutions
- Read the ref name in the error message and check whether it still exists (SELECT name FROM dolt_remote_branches); refs deleted concurrently can simply be skipped and the call retried.
- Retry PruneRemoteRefs — it is idempotent per ref and the error tells you where to resume (refs before it were already pruned).
- If the context was cancelled, re-run with a fresh context; already-deleted refs will not error on a second pass.
- Check Dolt engine logs for the underlying DOLT_BRANCH failure if retries keep failing (permissions, read-only mode, or engine bug).
Example fix
// before
pruned, err := versioncontrolops.PruneRemoteRefs(ctx, db)
if err != nil { return err } // treats partial success as total failure
// after: handle partial results and retry remaining refs
pruned, err := versioncontrolops.PruneRemoteRefs(ctx, db)
if err != nil {
log.Printf("pruned %d refs before failure: %v", len(pruned), err)
// retry is safe: remaining refs are still listed and deleted
_, err = versioncontrolops.PruneRemoteRefs(ctx, db)
} Defensive patterns
Strategy: retry
Validate before calling
rows, err := db.QueryContext(ctx, "SELECT name FROM dolt_remote_branches ORDER BY name")
if err != nil {
return err
}
// snapshot refs immediately before pruning to reduce concurrent-modification risk Try / catch
pruned, err := versioncontrolops.PruneRemoteRefs(ctx, db)
if err != nil {
// pruned holds refs deleted before the failure; retry is safe and resumes where it stopped
log.Printf("partial prune (%d done): %v", len(pruned), err)
time.Sleep(retryDelay)
_, err = versioncontrolops.PruneRemoteRefs(ctx, db)
} Prevention
- Treat PruneRemoteRefs as idempotent and retry on failure — already-deleted refs are skipped on the next pass.
- Avoid running concurrent fetch/push while pruning remote-tracking refs.
- Give the pruning loop a generous context timeout for many refs.
- Inspect the ref name in the error message to diagnose engine-side DOLT_BRANCH failures.
When it happens
Trigger: Calling PruneRemoteRefs when CALL DOLT_BRANCH('-D', '-r', ?) fails for a ref: the ref vanished concurrently, the Dolt engine rejects the delete, the connection breaks mid-loop, or the context is cancelled partway through the batch.
Common situations: Another process fetched/pushed and removed or recreated the ref while pruning; Dolt server-side constraint or permission error on DOLT_BRANCH; network drop or timeout during a long pruning loop; embedded Dolt refusing the call in a read-only session.
Related errors
- dolt_stats_gc: %w
- failed to add remote %s: %w
- db: %s: %w
- flatten step %q: %w
- failed to resolve schema_migrations conflicts: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/246f2637c07d3f82.
Report an issue: GitHub.