gastownhall/beads · error

db: DependencySQLRepository.CountAllForIDs from %s: %w

Error message

db: DependencySQLRepository.CountAllForIDs from %s: %w

What it means

CountAllForIDs runs SELECT COUNT(*) over dependencies (or wisp_dependencies) batches and scans the result. This error wraps any Scan/SQL failure of that count query, except the tolerated 'table not exist' case when opts.UseWispsTable is set (missing wisps table counts as zero). It means the counting query itself failed against the given table.

Source

Thrown at internal/storage/domain/db/dependency.go:818

		args := make([]any, 0, 2*len(batch))
		for i, id := range batch {
			placeholders[i] = "?"
			args = append(args, id)
		}
		for _, id := range batch {
			args = append(args, id)
		}
		ph := strings.Join(placeholders, ",")
		var count int
		//nolint:gosec // G201: table is one of two hardcoded constants; ? placeholders only.
		err := r.runner.QueryRowContext(ctx,
			fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE issue_id IN (%s) OR %s IN (%s)", table, ph, issueops.DepTargetExpr, ph),
			args...).Scan(&count)
		if err != nil {
			if opts.UseWispsTable && dberrors.IsTableNotExist(err) {
				return total, nil
			}
			return total, fmt.Errorf("db: DependencySQLRepository.CountAllForIDs from %s: %w", table, err)
		}
		total += count
	}
	return total, nil
}

func (r *dependencySQLRepositoryImpl) ListWithIssueMetadata(ctx context.Context, sourceID string, opts domain.DepListOpts) ([]*types.IssueWithDependencyMetadata, error) {
	var out []*types.IssueWithDependencyMetadata
	if opts.Direction == domain.DepDirectionOut || opts.Direction == domain.DepDirectionBoth {
		deps, err := issueops.GetDependenciesWithMetadataInTx(ctx, r.runner, sourceID)
		if err != nil {
			return nil, err
		}
		out = append(out, filterDepsByType(deps, opts.Types)...)
	}
	if opts.Direction == domain.DepDirectionIn || opts.Direction == domain.DepDirectionBoth {
		deps, err := issueops.GetDependentsWithMetadataInTx(ctx, r.runner, sourceID)
		if err != nil {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check the table named in the error exists; run database repair/migration if it is missing.
  2. If you intend wisp counts, set opts.UseWispsTable so a missing wisp_dependencies table is tolerated as zero.
  3. Verify database connectivity and re-run the count.
  4. Inspect the wrapped cause (%w) with errors.Unwrap for the driver-specific error.

Example fix

// before: opts missing wisps flag, missing wisp table becomes hard error
n, err := repo.CountAllForIDs(ctx, ids, domain.DepCountsOpts{})
// after: tolerate missing wisp table
total, err := repo.CountAllForIDs(ctx, ids, domain.DepCountsOpts{UseWispsTable: true})
Defensive patterns

Strategy: fallback

Validate before calling

if useWisps && !wispTableExists(ctx, db) {
    // missing wisp table counts as zero only with UseWispsTable set
    opts.UseWispsTable = true
}

Type guard

func isMissingTableErr(err error) bool {
    return dberrors.IsTableNotExist(err)
}

Try / catch

n, err := repo.CountAllForIDs(ctx, ids, opts)
if err != nil {
    if dberrors.IsTableNotExist(errors.Unwrap(err)) {
        n = 0 // treat missing table as no rows
    } else {
        return fmt.Errorf("dep count: %w", err)
    }
}

Prevention

When it happens

Trigger: Calling CountAllForIDs(ctx, ids, opts) where the COUNT query errors: unknown table (when not tolerating it), SQL syntax/engine error, connection failure, or scan failure on the count column.

Common situations: Corrupted or missing dependencies table after a failed migration; querying wisp_dependencies without UseWispsTable set so the missing-table tolerance is bypassed; database connection dropped mid-batch.

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