gastownhall/beads · error

db: LabelSQLRepository.ListByIssueIDs: %w

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.

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)

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.