gastownhall/beads · error

checking issue count: %w

Error message

checking issue count: %w

What it means

Wraps the error from ScanIssueCountsInTx during the import path (ensureConfig/import step) when the store checks inside a transaction whether the database is empty (total issues == 0) before importing config entries and issues. The count query failed — SQL error, transaction/connection problem, or context cancellation — so the store cannot safely decide whether to import and aborts the operation.

Source

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

}

// ImportJSONLData atomically checks if the database is empty and, if so,
// imports parsed issues and config key/value pairs in a single transaction.
// Returns the count of issues imported, or 0 if the database was not empty.
// Does NOT issue DOLT_COMMIT — the caller is responsible for committing
// (e.g. via the PersistentPostRun auto-commit hook).
func (s *EmbeddedDoltStore) ImportJSONLData(
	ctx context.Context,
	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 {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Run 'bd migrate' / open once normally so the schema is up to date, then retry the import.
  2. Check the wrapped inner error for the exact SQL failure and address it (missing table → migrate; lock → retry).
  3. Retry the import — the empty-check plus transaction design makes it safe to re-run.
  4. Ensure the context stays alive for the duration of the import.

Example fix

// before
store.ImportIssues(ctx, issues, cfgEntries) // ctx cancelled mid-import

// after
importCtx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()
store.ImportIssues(importCtx, issues, cfgEntries)
Defensive patterns

Strategy: retry

Validate before calling

if err := ctx.Err(); err != nil { return err }
// ensure schema is current before importing
if out, err := exec.Command("bd", "migrate").CombinedOutput(); err != nil {
    return fmt.Errorf("migrate before import: %v: %s", err, out)
}

Try / catch

err := store.ImportIssues(ctx, issues, cfg)
if err != nil && strings.Contains(err.Error(), "checking issue count") {
    // safe to retry: transactional, DB left untouched
    return store.ImportIssues(ctx, issues, cfg)
}

Prevention

When it happens

Trigger: Calling the import path (e.g. ImportIssues/BatchCreate with configEntries) on an EmbeddedDoltStore where: (1) the SELECT counting issues fails (schema missing/mismatched — e.g. migrations not applied); (2) the write transaction's connection breaks; (3) ctx is cancelled mid-query.

Common situations: Opening a database whose schema wasn't fully migrated, then attempting an import; engine hiccup or killed process mid-transaction; cancelled context in a long import script.

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/a6caf4926093c8bf. Report an issue: GitHub.