gastownhall/beads · error
remove label: id must not be empty
Error message
remove label: id must not be empty
What it means
A guard error from the label use case's remove(): it rejects removing a label when the target issue/wisp ID is empty. Called by RemoveLabel and RemoveWispLabel before any repository delete occurs.
Source
Thrown at internal/storage/domain/label.go:82
return fmt.Errorf("add label: label must not be empty")
}
if err := u.labelRepo.Insert(ctx, id, label, actor, LabelOpts{UseWispsTable: useWisp}); err != nil {
return fmt.Errorf("add label %s/%s: %w", id, label, err)
}
return nil
}
func (u *labelUseCaseImpl) RemoveLabel(ctx context.Context, issueID, label, actor string) error {
return u.remove(ctx, issueID, label, actor, false)
}
func (u *labelUseCaseImpl) RemoveWispLabel(ctx context.Context, wispID, label, actor string) error {
return u.remove(ctx, wispID, label, actor, true)
}
func (u *labelUseCaseImpl) remove(ctx context.Context, id, label, actor string, useWisp bool) error {
if id == "" {
return fmt.Errorf("remove label: id must not be empty")
}
if label == "" {
return fmt.Errorf("remove label: label must not be empty")
}
if err := u.labelRepo.Delete(ctx, id, label, actor, LabelOpts{UseWispsTable: useWisp}); err != nil {
return fmt.Errorf("remove label %s/%s: %w", id, label, err)
}
return nil
}
func (u *labelUseCaseImpl) AddLabels(ctx context.Context, issueID string, labels []string, actor string) error {
return u.addMany(ctx, issueID, labels, actor, false)
}
func (u *labelUseCaseImpl) AddWispLabels(ctx context.Context, wispID string, labels []string, actor string) error {
return u.addMany(ctx, wispID, labels, actor, true)
}
View on GitHub (pinned to 71377f2769)
Solutions
- Pass a resolved, non-empty issue ID to RemoveLabel/RemoveWispLabel.
- Fix the upstream lookup that returned an empty ID (check errors from the fetch, not just the value).
- In batch scripts, skip entries with empty IDs instead of calling remove for them.
- Validate input at the CLI/tool boundary before invoking the use case.
Example fix
// before
labelUC.RemoveLabel(ctx, os.Args[1], "stale", actor) // may be empty
// after
if len(os.Args) < 2 || os.Args[1] == "" {
return fmt.Errorf("usage: tool <issue-id> <label>")
}
labelUC.RemoveLabel(ctx, os.Args[1], "stale", actor) Defensive patterns
Strategy: validation
Validate before calling
func removeLabelSafe(ctx context.Context, uc LabelUseCase, id, label, actor string) error {
if strings.TrimSpace(id) == "" {
return errors.New("remove label: issue ID is required")
}
return uc.RemoveLabel(ctx, id, label, actor)
} Type guard
func hasIssueID(id string) bool { return strings.TrimSpace(id) != "" } Try / catch
if err := uc.RemoveLabel(ctx, id, label, actor); err != nil {
if strings.Contains(err.Error(), "id must not be empty") {
return fmt.Errorf("caller bug: unresolved issue ID")
}
return err
} Prevention
- Skip list entries with blank IDs before calling remove in batch scripts
- Check errors (not just values) from upstream ID lookups
- Validate IDs at the CLI/tool boundary
- Log-and-skip rather than call remove with an unresolved ID
When it happens
Trigger: Calling RemoveLabel(ctx, "", label, actor) or RemoveWispLabel(ctx, "", label, actor) — the ID argument is "", usually from an unpopulated variable or a failed upstream lookup.
Common situations: Scripts where the issue key variable is unset; piping lists into a removal loop where some rows have blank IDs; tests/tools calling the Go API with a placeholder empty ID.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- add label: id must not be empty
- add label: label must not be empty
- remove label: label must not be empty
- inherit labels: childID must not be empty
- inherit labels: parentID must not be empty
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/c8ecef5a64109516.
Report an issue: GitHub.