gastownhall/beads · error

dolt gc: %w

Error message

dolt gc: %w

What it means

DoltGC executes `CALL DOLT_GC('--archive-level', '0')` to reclaim disk space. The wrapped "dolt gc: %w" error means the stored procedure itself failed. The most common cause is calling it on a connection with an active explicit transaction — DOLT_GC cannot run inside one — or on a Dolt version/engine that lacks the procedure or the --archive-level flag.

Source

Thrown at internal/storage/versioncontrolops/gc.go:14

package versioncontrolops

import (
	"context"
	"fmt"
)

// DoltGC runs Dolt garbage collection to reclaim disk space. Archive level 0
// writes classic Snappy table files instead of zstd archives.
// conn must be a non-transactional database connection since
// DOLT_GC cannot run inside an explicit transaction.
func DoltGC(ctx context.Context, conn DBConn) error {
	if _, err := conn.ExecContext(ctx, "CALL DOLT_GC('--archive-level', '0')"); err != nil {
		return fmt.Errorf("dolt gc: %w", err)
	}
	return nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Ensure conn is a plain autocommit connection (pinned *sql.Conn or *sql.DB), never a *sql.Tx or a session inside an explicit transaction
  2. Commit/rollback any open transaction before calling DoltGC
  3. Check the Dolt server version supports DOLT_GC with --archive-level; drop the flag or upgrade if not
  4. Inspect the wrapped error for 'cannot run in a transaction' vs 'unknown procedure' to distinguish the causes

Example fix

// before: fails — tx connection
err := versioncontrolops.DoltGC(ctx, tx)
// after: use a non-transactional connection
tx.Rollback()
conn, _ := db.Conn(ctx)
defer conn.Close()
err := versioncontrolops.DoltGC(ctx, conn)
Defensive patterns

Strategy: try-catch

Validate before calling

// DOLT_GC cannot run inside an explicit transaction — verify autocommit first
var inTx int
_ = conn.QueryRowContext(ctx, "SELECT @@autocommit").Scan(&inTx)
if inTx != 1 {
	return errors.New("DoltGC requires a non-transactional autocommit connection")
}

Type guard

func isTxErr(err error) bool { return strings.Contains(err.Error(), "transaction") }
func isUnknownProc(err error) bool { return strings.Contains(err.Error(), "DOLT_GC") && strings.Contains(err.Error(), "not found") }

Try / catch

err := versioncontrolops.DoltGC(ctx, conn)
if err != nil {
	if isTxErr(err) {
		return fmt.Errorf("call DoltGC outside any transaction: %w", err)
	}
	return fmt.Errorf("gc failed: %w", err)
}

Prevention

When it happens

Trigger: Calling DoltGC with a *sql.Tx or a connection inside BEGIN/COMMIT; running against an old Dolt server that predates DOLT_GC or the --archive-level option; the server refusing GC while other sessions hold the database.

Common situations: Post-flatten cleanup where the caller reused a transactional connection; mixed bd/Dolt versions where archive-level 0 is unsupported; concurrent bd processes keeping the database busy.

Related errors


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