gastownhall/beads · error
db: SetConfig %s: %w
Error message
db: SetConfig %s: %w
What it means
This error wraps failure of the REPLACE INTO config statement inside SetConfig. SetConfig writes a config key/value and then re-syncs the normalized lookup tables (custom_types, custom_statuses); this wrapper specifically covers the initial row write failing. The SQL repo intentionally mirrors DoltStore.SetConfig semantics so both backends behave identically.
Source
Thrown at internal/storage/domain/db/config.go:83
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" {
value = strings.TrimSuffix(value, "-")
}
if _, err := r.runner.ExecContext(ctx, "REPLACE INTO config (`key`, value) VALUES (?, ?)", key, value); err != nil {
return fmt.Errorf("db: SetConfig %s: %w", key, err)
}
// Re-sync the normalized lookup table a value backs, mirroring
// DoltStore.SetConfig. Reads are TABLE-FIRST — GetCustomTypes above
// consults custom_types and falls back to the string only when the table is
// empty, and GetCustomStatuses reads custom_statuses outright — so a write
// that updated only the string left the table holding the previous set,
// forever: `bd config set types.custom` on a proxied deployment reported
// success and `bd create -t <the new type>` kept answering "invalid issue
// type", with doctor re-verifying against the string and reporting all-OK.
//
// The caller supplies a transactional runner, so the row and its projection
// commit together or neither does.
if _, err := issueops.SyncConfigTables(ctx, r.runner, key, value); err != nil {
return fmt.Errorf("db: SetConfig %s: %w", key, err)
}
return nil
}
View on GitHub (pinned to 71377f2769)
Solutions
- Run schema setup/migration (e.g. `bd doctor`) to ensure the config table exists
- Retry after confirming no other process holds the database lock
- Check disk space and write permissions on the database file
- Inspect the wrapped cause and address the specific driver error
- Restore from backup if the database is corrupted
Defensive patterns
Strategy: retry
Validate before calling
if err := ensureSchemaMigrated(ctx); err != nil {
return fmt.Errorf("config table unavailable: %w", err)
}
if locked := dbLockedByOtherProcess(); locked {
return fmt.Errorf("database locked by another bd process")
} Try / catch
err := retry.Do(3, retry.Backoff(time.Second), func() error {
return repo.SetConfig(ctx, key, value)
})
if err != nil {
return fmt.Errorf("could not set config %q after retries: %w", key, err)
} Prevention
- Retry transient lock/IO failures with backoff before surfacing
- Migrate schema after bd upgrades so the config table exists
- Verify write permissions and disk space before bulk config changes
- Use `bd config set` rather than editing the database directly
When it happens
Trigger: Calling SetConfig(ctx, key, value) when the REPLACE INTO config (`key`, value) ExecContext fails: missing config table, database lock, connection loss, or driver constraint/IO error.
Common situations: Running `bd config set` or prefix setup against a stale-schema database; concurrent bd processes contending for the DB lock; disk full while writing; an old binary opening a migrated database.
Related errors
- db: SetLocalMetadata %s: %w
- ErrExec
- database not available: %w
- failed to load config: %w
- search gates: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/c225b39dcd95de56.
Report an issue: GitHub.