gastownhall/beads · error

db: LabelSQLRepository.ListByIssueIDs

Error message

db: LabelSQLRepository.ListByIssueIDs: %w

What it means

LabelSQLRepository.ListByIssueIDs failed to execute its SELECT of (issue_id, label) for the given issue IDs. The database rejected or failed to run the query, so no rows were returned at all.

Solutions

  1. Unwrap the error to see the driver cause (no such table, syntax, too many parameters)
  2. Verify the labels table exists: run schema setup/migrations before repository calls
  3. Reduce the size of issueIDs (batch the call) if hitting placeholder/parameter limits
  4. If using wisps table mode, confirm the wisps labels table exists or handle IsTableNotExist upstream

Example fix

// before
result, err := repo.ListByIssueIDs(ctx, thousandsOfIDs, opts)
// after
for i := 0; i < len(ids); i += 500 {
    batch := ids[i:min(i+500, len(ids))]
    r, err := repo.ListByIssueIDs(ctx, batch, opts)
    ...
}
Defensive patterns

Strategy: validation

Validate before calling

// validate inputs and schema before the call
if len(issueIDs) == 0 { return map[string][]string{}, nil }
if len(issueIDs) > 500 { /* batch */ }
// confirm table exists
var one int
err := db.QueryRow(`SELECT 1 FROM sqlite_master/dolt_tables WHERE name='issue_labels'`).Scan(&one)

Try / catch

m, err := repo.ListByIssueIDs(ctx, ids, opts)
if err != nil {
    if dberrors.IsTableNotExist(errors.Unwrap(err)) {
        return map[string][]string{}, nil
    }
    return err
}

Prevention

When it happens

Trigger: Calling ListByIssueIDs with a malformed IN-clause (built from issueIDs), or when the labels table does not exist (e.g. wisps table mode enabled but table absent), or the connection/query fails.

Common situations: Empty or huge issueIDs list producing too many placeholders beyond driver limits; labels table not yet created because schema migrations did not run; querying wisps table that was never materialized; database locked or unreachable.

Related errors


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

Appendix: source

Thrown at internal/storage/domain/db/label.go:172

	result := make(map[string][]string)
	if len(issueIDs) == 0 {
		return result, nil
	}
	placeholders := make([]string, len(issueIDs))
	args := make([]any, len(issueIDs))
	for i, id := range issueIDs {
		placeholders[i] = "?"
		args[i] = id
	}
	table := pickLabelTable(opts.UseWispsTable)
	//nolint:gosec // G201: table is one of two hardcoded constants
	q := fmt.Sprintf(
		"SELECT issue_id, label FROM %s WHERE issue_id IN (%s) ORDER BY issue_id, label",
		table, strings.Join(placeholders, ","),
	)
	rows, err := r.runner.QueryContext(ctx, q, args...)
	if err != nil {
		return nil, fmt.Errorf("db: LabelSQLRepository.ListByIssueIDs: %w", err)
	}
	defer rows.Close()

	for rows.Next() {
		var issueID, label string
		if err := rows.Scan(&issueID, &label); err != nil {
			return nil, fmt.Errorf("db: LabelSQLRepository.ListByIssueIDs: scan: %w", err)
		}
		result[issueID] = append(result[issueID], label)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("db: LabelSQLRepository.ListByIssueIDs: rows: %w", err)
	}
	return result, nil
}

func (r *labelSQLRepositoryImpl) DeleteAllForIDs(ctx context.Context, ids []string, opts domain.LabelOpts) (int, error) {
	if len(ids) == 0 {

View on GitHub (pinned to 71377f2769)