gastownhall/beads · error

open gc connection: %w

Error message

open gc connection: %w

What it means

runShutdownGC opens a temporary sql.DB connection (driver "mysql") to the Dolt server using DSN(ctx, database, "root", "") to run shutdown garbage collection. This error wraps a failure from sql.Open — most commonly the MySQL driver registration or malformed DSN.

Source

Thrown at internal/storage/dbproxy/server/doltserver.go:393

	}
	var rmErr error
	if s.pid != 0 {
		rmErr = pidfile.Remove(s.rootDir, PIDFileName)
		s.pid = 0
	}
	if rmErr != nil {
		rmErr = fmt.Errorf("server: DoltServer.Stop: remove pidfile: %w", rmErr)
	}
	return errors.Join(gcErr, waitErr, closeErr, rmErr)
}

func (s *DoltServer) runShutdownGC(ctx context.Context) (retErr error) {
	if s.database == "" || !s.Running(ctx) {
		return nil
	}
	db, err := sql.Open("mysql", s.DSN(ctx, s.database, "root", ""))
	if err != nil {
		return fmt.Errorf("open gc connection: %w", err)
	}
	defer func() { retErr = errors.Join(retErr, db.Close()) }()

	conn, err := db.Conn(ctx)
	if err != nil {
		return fmt.Errorf("acquire gc connection: %w", err)
	}
	defer func() { retErr = errors.Join(retErr, conn.Close()) }()

	if err := versioncontrolops.DoltGC(ctx, conn); err != nil {
		retErr = errors.Join(retErr, err)
	}
	if _, err := conn.ExecContext(ctx, "CALL DOLT_STATS_GC()"); err != nil {
		retErr = errors.Join(retErr, fmt.Errorf("dolt_stats_gc: %w", err))
	}
	return retErr
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check the generated DSN (log s.DSN(...)) for invalid characters, especially in the database name
  2. Ensure the mysql driver is linked via import _ "github.com/go-sql-driver/mysql"
  3. Confirm s.database is the correct non-empty database name; empty name skips GC entirely
  4. Retry Stop — transient DSN parsing is rare, but configuration errors are deterministic and must be fixed

Example fix

// before
import "database/sql"
// after
import (
    "database/sql"
    _ "github.com/go-sql-driver/mysql" // register "mysql" driver
)
Defensive patterns

Strategy: validation

Validate before calling

import (
    _ "github.com/go-sql-driver/mysql" // ensure driver registered at init
)
// sanity-check DSN before Stop
func validDSN(d string) bool {
    cfg, err := mysql.ParseDSN(d)
    return err == nil && cfg.DBName != ""
}

Try / catch

if err := server.Stop(ctx); err != nil {
    var openErr error
    if strings.Contains(err.Error(), "open gc connection") {
        openErr = fmt.Errorf("shutdown GC unavailable, check mysql driver/DSN: %w", err)
    }
    return openErr // or log-and-continue if GC is optional
}

Prevention

When it happens

Trigger: DoltServer.Stop invoked on a running server with a non-empty s.database, and sql.Open("mysql", dsn) returns an error — typically an invalid DSN (bad characters in database name/host) or the mysql driver not being registered in the binary.

Common situations: Database name containing characters needing DSN escaping; a blank-import of the mysql driver removed during refactoring so "mysql" is unknown; empty password/root user disallowed by config feeding into DSN.

Related errors


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