gastownhall/beads · error

setting issue_prefix: %w

Error message

setting issue_prefix: %w

What it means

Wraps the error from SetConfigInTx when auto-detecting and persisting the issue_prefix config: if the caller's configEntries lacks "issue_prefix", the store extracts the prefix from the first issue's ID (utils.ExtractIssuePrefix) and writes it in the same import transaction. Failure means the config row write failed (SQL error, table missing, transaction issue), rolling back the entire import so the database remains empty and the import retryable.

Source

Thrown at internal/storage/embeddeddolt/store.go:763

		}

		// 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 transaction
		if err := issueops.CreateIssuesInTx(ctx, tx, issues, actor, storage.BatchCreateOptions{
			SkipPrefixValidation: true,
			// Defense-in-depth (GH#3955): the embedded fast-path is the primary
			// auto-import route for 1.0+ users and is gated by the in-transaction
			// emptiness check above. Make it insert-if-new too so a regression in
			// that check cannot clobber live rows — matching the server-mode
			// fallback's conflict-skip behavior.
			ConflictSkip: true,
		}); err != nil {
			return err
		}

		imported = len(issues)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Migrate the schema first ('bd migrate'), then retry the import.
  2. Explicitly pass issue_prefix in configEntries so the auto-detect write path is skipped and the prefix is deterministic.
  3. Check the wrapped inner SQL error for the root cause (missing table vs. connection).
  4. Retry — the transactional rollback makes re-import safe.
  5. Validate that issue IDs in the import file follow the expected 'prefix-N' format.

Example fix

// before
store.ImportIssues(ctx, issues, map[string]string{}) // prefix auto-detected from "weird_id_1"

// after
store.ImportIssues(ctx, issues, map[string]string{"issue_prefix": "bd"})
Defensive patterns

Strategy: validation

Validate before calling

// decide the prefix up front to skip auto-detection
prefix := "bd"
if len(issues) > 0 {
    if p := utils.ExtractIssuePrefix(issues[0].ID); p != "" { prefix = p }
}
cfg["issue_prefix"] = prefix

Try / catch

err := store.ImportIssues(ctx, issues, cfg)
if err != nil && strings.Contains(err.Error(), "setting issue_prefix") {
    // transaction rolled back; supply explicit prefix and retry
    cfg["issue_prefix"] = "bd"
    return store.ImportIssues(ctx, issues, cfg)
}

Prevention

When it happens

Trigger: Import where configEntries has no "issue_prefix" and: (1) the config table is absent due to unmigrated schema; (2) the write fails from connection loss or ctx cancellation mid-transaction; (3) a constraint error on the config table. Only triggered when len(issues) > 0 and the first issue's ID yields a non-empty prefix (e.g. "bd-123" → "bd").

Common situations: Importing a hand-edited or tool-generated issues.jsonl whose IDs lack a recognizable prefix (prefix extracted as empty is skipped — but malformed IDs with odd prefixes can still exercise this path); importing into a database whose schema wasn't migrated; CI cancellation during import.

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


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