gastownhall/beads · error

count dependencies: %w

Error message

count dependencies: %w

What it means

DeleteResolvedSetInTx wraps a failure from CountRowsForIssueIDsInTx on the dependencies table (a later, distinct wrap covers wisp_dependencies). These counts feed the delete result/audit summary of how many child rows will disappear; the failure aborts before any rows are counted/deleted inconsistently.

Source

Thrown at internal/storage/issueops/delete.go:213

// neighborhood BEFORE the delete and rewrite it AFTER against the SAME
// DeletionSet the delete was handed.
//
//nolint:gosec // G201: inClause contains only ? placeholders
func DeleteResolvedSetInTx(ctx context.Context, tx *sql.Tx, set DeletionSet, dryRun bool) (*types.DeleteIssuesResult, error) {
	result := &types.DeleteIssuesResult{}
	if len(set.All) == 0 {
		return result, nil
	}

	deletedSet := make(map[string]bool, len(set.All))
	for _, id := range set.All {
		deletedSet[id] = true
	}

	var depsCount, labelsCount, eventsCount int
	var err error
	if depsCount, err = CountRowsForIssueIDsInTx(ctx, tx, "dependencies", set.RegularIDs); err != nil {
		return nil, fmt.Errorf("count dependencies: %w", err)
	}
	wispDepsCount, err := CountRowsForIssueIDsInTx(ctx, tx, "wisp_dependencies", set.WispIDs)
	if err != nil {
		return nil, fmt.Errorf("count wisp dependencies: %w", err)
	}
	depsCount += wispDepsCount

	if labelsCount, err = CountRowsForIssueIDsInTx(ctx, tx, "labels", set.RegularIDs); err != nil {
		return nil, fmt.Errorf("count labels: %w", err)
	}
	wispLabelsCount, err := CountRowsForIssueIDsInTx(ctx, tx, "wisp_labels", set.WispIDs)
	if err != nil {
		return nil, fmt.Errorf("count wisp labels: %w", err)
	}
	labelsCount += wispLabelsCount

	if eventsCount, err = CountRowsForIssueIDsInTx(ctx, tx, "events", set.RegularIDs); err != nil {
		return nil, fmt.Errorf("count events: %w", err)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the wrapped error; a missing 'dependencies' table means run schema migration.
  2. Retry the delete with a longer-lived context sized to the batch.
  3. Reduce batch size so counting stays within statement timeouts.
  4. Retry in a fresh transaction if the cause was a dropped connection.
Defensive patterns

Strategy: validation

Validate before calling

// schema pre-flight for the counted tables
for _, t := range []string{"dependencies", "wisp_dependencies"} {
	if err := tableExists(ctx, db, t); err != nil { return err }
}

Try / catch

res, err := storage.DeleteIssues(ctx, db, ids, cascade, force, dryRun)
if err != nil {
	if errors.Is(err, context.DeadlineExceeded) { /* longer ctx, smaller batch */ }
	if strings.Contains(causeOf(err).Error(), "no such table") { /* run migrations */ }
	return err
}

Prevention

When it happens

Trigger: Bulk delete reaching the row-counting phase when the SELECT COUNT on dependencies for the regular ids fails: context expired mid-bulk-delete, connection dropped, or SQL error (e.g., table missing after schema drift).

Common situations: Very large bulk deletes whose context budget runs out during counting; schema drift after an upgrade removing/renaming the dependencies table; transient Dolt server errors on big IN(...) queries.

Related errors


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