gastownhall/beads · error
importing config %q: %w
Error message
importing config %q: %w
What it means
Wraps the error from SetConfigInTx while writing each config entry (key/value, e.g. memories) inside the import transaction. The issue-count check passed (database is empty), but persisting a config row failed — SQL error such as a missing/corrupt config table, constraint violation, or connection/context failure. Because this happens inside the import transaction, the whole import transaction is rolled back, leaving the database still empty and the import safely retryable.
Source
Thrown at internal/storage/embeddeddolt/store.go:750
issues []*types.Issue,
configEntries map[string]string,
actor string,
) (int, error) {
var imported int
err := s.withConn(ctx, true, func(tx *sql.Tx) error {
// Atomically check: is the database empty?
stats := &types.Statistics{}
if err := issueops.ScanIssueCountsInTx(ctx, tx, stats); err != nil {
return fmt.Errorf("checking issue count: %w", err)
}
if stats.TotalIssues > 0 {
return nil // database is not empty — skip import
}
// Import config entries (memories, etc.)
for key, value := range configEntries {
if err := issueops.SetConfigInTx(ctx, tx, key, value); err != nil {
return fmt.Errorf("importing config %q: %w", key, err)
}
}
if len(issues) == 0 {
return nil
}
// Auto-detect prefix from first issue if not already provided
if _, hasPrefix := configEntries["issue_prefix"]; !hasPrefix {
firstPrefix := utils.ExtractIssuePrefix(issues[0].ID)
if firstPrefix != "" {
if err := issueops.SetConfigInTx(ctx, tx, "issue_prefix", firstPrefix); err != nil {
return fmt.Errorf("setting issue_prefix: %w", err)
}
}
}
// Create all issues in the same transactionView on GitHub (pinned to 71377f2769)
Solutions
- Apply migrations first ('bd migrate' or open once via bd) so the config table exists, then retry.
- Inspect the wrapped key (%q) and inner SQL error to find the offending config entry.
- Retry the import — transactional rollback keeps the DB empty, so a rerun is idempotent.
- Sanitize/canonicalize config keys in the source export if a specific key is malformed.
Example fix
// before
entries := map[string]string{"issue_prefix": "bd", "issue_prefix ": "xx"} // duplicate/odd key
store.ImportIssues(ctx, issues, entries)
// after
delete(entries, "issue_prefix ") // remove conflicting key
store.ImportIssues(ctx, issues, entries) Defensive patterns
Strategy: retry
Validate before calling
for key := range configEntries {
if strings.TrimSpace(key) == "" || strings.ContainsAny(key, "\n\r") {
return fmt.Errorf("invalid config key %q", key)
}
} Try / catch
err := store.ImportIssues(ctx, issues, cfg)
if err != nil && strings.Contains(err.Error(), "importing config") {
// rollback already happened; fix offending key per error text, then retry
return store.ImportIssues(ctx, issues, sanitizeConfig(cfg))
} Prevention
- Migrate the schema before importing
- Deduplicate and normalize config keys in source exports
- Use one long-lived context for the entire import
- Rely on transaction rollback: failed imports leave the DB empty and retryable
When it happens
Trigger: Import path with configEntries where: (1) the config table doesn't exist (unmigrated schema); (2) a duplicate-key or constraint error on the config key; (3) ctx cancelled mid-loop; (4) transaction connection lost after several writes.
Common situations: Importing into a freshly created but unmigrated database; importing a .beads/issues.jsonl export whose config keys collide with an existing (partially imported) dataset; long imports cancelled by CI timeouts.
Understand the failure class
Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.
Related errors
- setting issue_prefix: %w
- checking issue count: %w
- failed to import config %q: %w
- failed to set issue_prefix from imported issues: %w
- scan dirty config key: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/17a9659c07a2c72c.
Report an issue: GitHub.