gastownhall/beads · error

db: DependencySQLRepository.ListByIssueIDs (in): %w

Error message

db: DependencySQLRepository.ListByIssueIDs (in): %w

What it means

Same as the (out) variant but for the incoming-direction query: SELECT ... WHERE depends_on_id IN (...), filling result.Incoming. Indicates the bulk incoming-dependency fetch failed at SQL execution or row-scan time.

Source

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

		q := fmt.Sprintf(
			`SELECT %s FROM %s WHERE issue_id IN (%s)%s ORDER BY issue_id`,
			depSelectColumns, table, idPlaceholders, typeWhere,
		)
		args := combineArgs(idArgs, typeArgs)
		if err := r.queryDeps(ctx, q, args, result.Outgoing, true); err != nil {
			return domain.DepBulkResult{}, fmt.Errorf("db: DependencySQLRepository.ListByIssueIDs (out): %w", err)
		}
	}

	if opts.Direction == domain.DepDirectionBoth || opts.Direction == domain.DepDirectionIn {
		//nolint:gosec // G201: table, depSelectColumns, depTargetExpr are hardcoded
		q := fmt.Sprintf(
			`SELECT %s FROM %s WHERE %s IN (%s)%s ORDER BY issue_id`,
			depSelectColumns, table, depTargetExpr, idPlaceholders, typeWhere,
		)
		args := combineArgs(idArgs, typeArgs)
		if err := r.queryDeps(ctx, q, args, result.Incoming, false); err != nil {
			return domain.DepBulkResult{}, fmt.Errorf("db: DependencySQLRepository.ListByIssueIDs (in): %w", err)
		}
	}

	return result, nil
}

func (r *dependencySQLRepositoryImpl) CountsByIssueIDs(ctx context.Context, issueIDs []string, opts domain.DepCountsOpts) (map[string]*types.DependencyCounts, error) {
	result := make(map[string]*types.DependencyCounts)
	if len(issueIDs) == 0 {
		return result, nil
	}
	for _, id := range issueIDs {
		result[id] = &types.DependencyCounts{}
	}

	idPlaceholders, idArgs := buildInPlaceholders(issueIDs)
	table := pickDepTable(opts.UseWispsTable)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Chunk the issueIDs list to stay within placeholder limits.
  2. Confirm the UseWispsTable flag matches the storage location of the deps.
  3. Retry on a healthy connection; read-only operation.
  4. Inspect dep rows for NULL/corrupt columns if scan errors persist after migration.

Example fix

// before
res, err := deps.ListByIssueIDs(ctx, ids, domain.DepListOpts{Direction: domain.DepDirectionIn})
// after: chunk + both directions merged
for batch := range slices.Chunk(ids, 500) {
    r, err := deps.ListByIssueIDs(ctx, batch, domain.DepListOpts{Direction: domain.DepDirectionBoth})
    if err != nil { return err }
    mergeInto(res, r)
}
Defensive patterns

Strategy: validation

Validate before calling

if len(issueIDs) == 0 { return domain.DepBulkResult{}, nil }
const maxBatch = 500
if len(issueIDs) > maxBatch { /* chunk before calling */ }

Try / catch

if err != nil && strings.Contains(err.Error(), "ListByIssueIDs (in)") {
    // retry read-only, or chunk and merge incoming maps
}

Prevention

When it happens

Trigger: ListByIssueIDs(ctx, issueIDs, opts) with Direction=Both or In; the incoming SELECT fails or scanning rows fails: placeholder limit exceeded, connection drop, table mismatch (UseWispsTable), corrupted dep rows failing scan.

Common situations: Bulk exports/loads of thousands of IDs; stale wisps-table flag after migration; driver errors from NULL/typed columns changed by a schema migration.

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