gastownhall/beads · error

failed to scan issue id: %w

Error message

failed to scan issue id: %w

What it means

While iterating rows from the issue id scan, rows.Scan(&id) can fail if a row's id column is NULL or has an unexpected type; that failure is wrapped here. It indicates malformed or unexpected data in the issues table rather than a query error.

Source

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

	}
	if err != sql.ErrNoRows {
		return fmt.Errorf("failed to check issue_counter for prefix %q: %w", prefix, err)
	}

	// No counter row yet. Scan existing issues to find the highest numeric suffix.
	likePattern := prefix + "-%"
	rows, err := tx.QueryContext(ctx, "SELECT id FROM issues WHERE id LIKE ?", likePattern)
	if err != nil {
		return fmt.Errorf("failed to query existing issues for prefix %q: %w", prefix, err)
	}
	defer rows.Close()

	maxNum := 0
	prefixDash := prefix + "-"
	for rows.Next() {
		var id string
		if err := rows.Scan(&id); err != nil {
			return fmt.Errorf("failed to scan issue id: %w", err)
		}
		// Strip the prefix and attempt to parse the remainder as an integer.
		suffix := strings.TrimPrefix(id, prefixDash)
		if suffix == id {
			// id did not start with prefix- (should not happen given LIKE, but be safe)
			continue
		}
		var num int
		if _, parseErr := fmt.Sscanf(suffix, "%d", &num); parseErr == nil && fmt.Sprintf("%d", num) == suffix {
			if num > maxNum {
				maxNum = num
			}
		}
	}
	if err := rows.Err(); err != nil {
		return fmt.Errorf("failed to iterate existing issues for prefix %q: %w", prefix, err)
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the issues table for rows with NULL or malformed id values and remove/repair them
  2. Run bd doctor for integrity checks
  3. Restore the database from a known-good backup if rows are corrupt
  4. Re-run the create/seed operation after cleanup
Defensive patterns

Strategy: validation

Validate before calling

// Detect rows with NULL/invalid ids
const bad = await query("SELECT COUNT(*) FROM issues WHERE id IS NULL OR id = ''");
if (bad > 0) throw new Error(`${bad} corrupt issue rows; repair before use`);

Type guard

function hasValidId(row) {
  return typeof row.id === "string" && /^[^\s]+-\d+$/.test(row.id);
}

Try / catch

try {
  await bd.create(title);
} catch (e) {
  if (String(e.message).includes("failed to scan issue id")) {
    // run integrity repair / bd doctor before retrying
  } else throw e;
}

Prevention

When it happens

Trigger: seedCounterFromExistingIssuesTx scanning an issues row whose id is NULL or non-string (schema corruption, manual edits, incompatible migration).

Common situations: Hand-edited databases, interrupted migrations, or imports that wrote rows violating the schema (NULL primary keys).

Related errors


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