gastownhall/beads · warning
db: LabelSQLRepository.Delete: label must not be empty
Error message
db: LabelSQLRepository.Delete: label must not be empty
What it means
Input validation error thrown by LabelSQLRepository.Delete when the label argument is an empty string. An empty label would not match any row meaningfully, so the repository rejects the call up front rather than executing a pointless DELETE and journaling a spurious event.
Source
Thrown at internal/storage/domain/db/label.go:95
if err := r.events.Record(ctx, domain.Event{
IssueID: issueID,
Type: types.EventLabelAdded,
Actor: actor,
NewValue: label,
}, domain.RecordEventOpts{UseWispsTable: opts.UseWispsTable}); err != nil {
return err
}
// A label is part of the bead snapshot; the idempotent no-op path above
// returns without writing and journals nothing.
return issueops.RecordEventInTx(ctx, r.runner, issueops.EventUpdate, issueID, actor)
}
func (r *labelSQLRepositoryImpl) Delete(ctx context.Context, issueID, label, actor string, opts domain.LabelOpts) error {
if issueID == "" {
return fmt.Errorf("db: LabelSQLRepository.Delete: issueID must not be empty")
}
if label == "" {
return fmt.Errorf("db: LabelSQLRepository.Delete: label must not be empty")
}
table := pickLabelTable(opts.UseWispsTable)
//nolint:gosec // G201: table is one of two hardcoded constants
result, err := r.runner.ExecContext(ctx,
fmt.Sprintf("DELETE FROM %s WHERE issue_id = ? AND label = ?", table),
issueID, label,
)
if err != nil {
return fmt.Errorf("db: LabelSQLRepository.Delete %s/%s: %w", issueID, label, err)
}
rows, err := result.RowsAffected()
if err != nil {
return fmt.Errorf("db: LabelSQLRepository.Delete %s/%s: rows affected: %w", issueID, label, err)
}
if rows == 0 {
return nil
}
if err := r.events.Record(ctx, domain.Event{View on GitHub (pinned to 71377f2769)
Solutions
- Ensure label is non-empty before calling Delete
- Validate/sanitize label input at the CLI/UI boundary
- Check string-splitting logic that produced an empty label
Example fix
// before
label := strings.TrimSpace(userLabel)
repo.Delete(ctx, issueID, label, actor, opts)
// after
label := strings.TrimSpace(userLabel)
if label == "" { return fmt.Errorf("label required") }
repo.Delete(ctx, issueID, label, actor, opts) Defensive patterns
Strategy: validation
Validate before calling
label = strings.TrimSpace(rawLabel)
if label == "" { return fmt.Errorf("label must not be empty") } Try / catch
if err := repo.Delete(ctx, issueID, label, actor, opts); err != nil {
if strings.Contains(err.Error(), "label must not be empty") { return fmt.Errorf("cannot remove empty label for %s", issueID) }
return err
} Prevention
- Trim and validate label input before repository calls
- Reject whitespace-only labels at the UI/CLI layer
- Check label-parsing/splitting logic for empty tokens
- Test Delete with empty and whitespace labels
When it happens
Trigger: Calling Delete(ctx, issueID, "", actor, opts) — e.g. a label variable lost in string processing, or user input stripped to empty by sanitization.
Common situations: Trimmed user input that was only whitespace; label field never set on a struct before persistence; parsing bug splitting labels on the wrong delimiter.
Related errors
- db: LabelSQLRepository.Delete: issueID must not be empty
- db: LabelSQLRepository.List: issueID must not be empty
- %s cannot be empty
- no rules to compact
- memory content cannot be empty
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/95e71847a948ddd8.
Report an issue: GitHub.