gastownhall/beads · error

db: SetLocalMetadata %s: %w

Error message

db: SetLocalMetadata %s: %w

What it means

This error wraps the underlying SQL driver failure from an INSERT/REPLACE into the local_metadata table in the Dolt-backed storage layer. SetLocalMetadata writes a key/value row used for repo-local metadata; when the ExecContext call fails, the error is wrapped as "db: SetLocalMetadata <key>: <cause>" so callers know which metadata key could not be persisted. The root cause is always in the wrapped driver error (connection loss, schema problem, constraint, etc.).

Source

Thrown at internal/storage/domain/db/config.go:61

	}
	return nil
}

func (r *configSQLRepositoryImpl) GetLocalMetadata(ctx context.Context, key string) (string, error) {
	var value string
	err := r.runner.QueryRowContext(ctx, "SELECT value FROM local_metadata WHERE `key` = ?", key).Scan(&value)
	if errors.Is(err, sql.ErrNoRows) {
		return "", nil
	}
	if err != nil {
		return "", fmt.Errorf("db: GetLocalMetadata %s: %w", key, err)
	}
	return value, nil
}

func (r *configSQLRepositoryImpl) SetLocalMetadata(ctx context.Context, key, value string) error {
	if _, err := r.runner.ExecContext(ctx, "REPLACE INTO local_metadata (`key`, value) VALUES (?, ?)", key, value); err != nil {
		return fmt.Errorf("db: SetLocalMetadata %s: %w", key, err)
	}
	return nil
}

func (r *configSQLRepositoryImpl) GetConfig(ctx context.Context, key string) (string, error) {
	var value string
	err := r.runner.QueryRowContext(ctx, "SELECT value FROM config WHERE `key` = ?", key).Scan(&value)
	if errors.Is(err, sql.ErrNoRows) {
		return "", nil
	}
	if err != nil {
		return "", fmt.Errorf("db: GetConfig %s: %w", key, err)
	}
	return value, nil
}

func (r *configSQLRepositoryImpl) SetConfig(ctx context.Context, key, value string) error {
	if key == "issue_prefix" {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Run the driver's schema/migration path (e.g. `bd doctor` or re-open the repo) to ensure the local_metadata table exists
  2. Inspect the wrapped cause (the %w chain) to identify whether it is I/O, locking, or schema related and fix accordingly
  3. Check disk space and file permissions on the database directory
  4. Ensure no other process holds a conflicting lock on the Dolt database, then retry
  5. If the database is corrupt, restore from backup or re-init the repo

Example fix

// before
if _, err := db.Exec("REPLACE INTO local_metadata (`key`, value) VALUES (?, ?)", k, v); err != nil {
	return fmt.Errorf("set failed")
}
// after
if _, err := db.Exec("REPLACE INTO local_metadata (`key`, value) VALUES (?, ?)", k, v); err != nil {
	return fmt.Errorf("db: SetLocalMetadata %s: %w", k, err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

if err := doctor.CheckSchema(ctx, repo); err != nil {
	return fmt.Errorf("schema not ready for local_metadata: %w", err)
}

Try / catch

if err := repo.SetLocalMetadata(ctx, key, value); err != nil {
	var drv *driver.Error
	if errors.As(err, &drv) {
		// inspect drv for lock/IO/table cause before retrying
	}
	return fmt.Errorf("persisting %q failed: %w", key, err)
}

Prevention

When it happens

Trigger: Calling SetLocalMetadata(ctx, key, value) when the REPLACE INTO local_metadata statement fails: database file corrupted or locked, local_metadata table missing (schema migration not run), connection dropped mid-write, or a driver-level constraint/IO error.

Common situations: Running bd commands against a .beads database whose schema predates the local_metadata table; disk full or database file corrupted after a crash; concurrent access locking the Dolt database; version mismatch where an older binary opens a newer schema.

Related errors


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