gastownhall/beads · error

failed to read issue_id_mode config: %w

Error message

failed to read issue_id_mode config: %w

What it means

isCounterModeTx reads the `issue_id_mode` key from the config table to decide whether to use counter-based IDs. This error wraps a failure reading that config row other than 'row not found' (ErrNoRows is treated as non-counter mode). It means the config table is unreadable, missing, or the query failed for connection/transaction reasons.

Source

Thrown at internal/storage/dolt/issues.go:907

			}
		}
	}

	// Read back the value that was atomically set by the DB engine.
	var nextID int
	err = tx.QueryRowContext(ctx, "SELECT last_id FROM issue_counter WHERE prefix = ?", prefix).Scan(&nextID)
	if err != nil {
		return "", fmt.Errorf("failed to read issue counter after increment for prefix %q: %w", prefix, err)
	}
	return fmt.Sprintf("%s-%d", prefix, nextID), nil
}

// isCounterModeTx checks whether issue_id_mode=counter is configured.
func isCounterModeTx(ctx context.Context, tx *sql.Tx) (bool, error) {
	var idMode string
	err := tx.QueryRowContext(ctx, "SELECT value FROM config WHERE `key` = ?", "issue_id_mode").Scan(&idMode)
	if err != nil && err != sql.ErrNoRows {
		return false, fmt.Errorf("failed to read issue_id_mode config: %w", err)
	}
	return idMode == "counter", nil
}

// generateHashID creates a hash-based ID for a top-level issue.
// Uses base36 encoding (0-9, a-z) for better information density than hex.
func generateHashID(prefix, title, description, creator string, timestamp time.Time, length, nonce int) string {
	return idgen.GenerateHashID(prefix, title, description, creator, timestamp, length, nonce)
}

// Thin wrappers around exported issueops functions, kept for internal callers.
var (
	isAllowedUpdateField = issueops.IsAllowedUpdateField
)

// Aliases for shared nullable helpers from issueops.
var (
	nullString    = issueops.NullString

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the wrapped cause; if the config table is missing, run the beads schema migration to create it.
  2. Re-run after confirming the Dolt backend is reachable and the context deadline is sufficient.
  3. Create the config row explicitly (INSERT INTO config (key, value) VALUES ('issue_id_mode','counter')) to force counter mode once the table exists.
  4. Run bd doctor to diagnose database corruption if errors persist.

Example fix

// before
err := tx.QueryRowContext(ctx, "SELECT value FROM config WHERE `key` = ?", "issue_id_mode").Scan(&idMode)
if err != nil && err != sql.ErrNoRows {
    return false, fmt.Errorf("failed to read issue_id_mode config: %w", err)
}
// after (fail with actionable hint)
err := tx.QueryRowContext(ctx, "SELECT value FROM config WHERE `key` = ?", "issue_id_mode").Scan(&idMode)
if err != nil && err != sql.ErrNoRows {
    if errors.Is(err, sql.ErrNoRows) { /* unreachable, kept for clarity */ }
    return false, fmt.Errorf("failed to read issue_id_mode config (is the config table migrated?): %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

var val string
err := db.QueryRow("SELECT value FROM config WHERE `key` = 'issue_id_mode'").Scan(&val)
if err != nil {
    if errors.Is(err, sql.ErrNoRows) { /* default mode, fine */ } else {
        return fmt.Errorf("config table unreadable; run schema migration: %w", err)
    }
}

Type guard

func isConfigReadErr(err error) bool {
    return err != nil && strings.Contains(err.Error(), "issue_id_mode config") && !errors.Is(err, sql.ErrNoRows)
}

Try / catch

id, err := store.CreateIssue(ctx, issue)
if err != nil && strings.Contains(err.Error(), "read issue_id_mode config") {
    return fmt.Errorf("config table problem; run bd doctor / schema migration: %w", err)
}

Prevention

When it happens

Trigger: Any issue-ID generation when the `SELECT value FROM config WHERE key = 'issue_id_mode'` fails: config table absent from an old schema, corrupted database, cancelled context, or transaction/connection error.

Common situations: Very old beads databases that predate the config table; a corrupt .beads database; a context timeout hitting during repository open; Dolt server unavailable mid-transaction.

Related errors


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