{"record":{"id":"6adfb9c82964cc5d","repo":"gastownhall/beads","slug":"add-labels-id-must-not-be-empty","errorCode":null,"errorMessage":"add labels: id must not be empty","messagePattern":"add labels: id must not be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/label.go","lineNumber":103,"sourceCode":"\t\treturn fmt.Errorf(\"remove label: label must not be empty\")\n\t}\n\tif err := u.labelRepo.Delete(ctx, id, label, actor, LabelOpts{UseWispsTable: useWisp}); err != nil {\n\t\treturn fmt.Errorf(\"remove label %s/%s: %w\", id, label, err)\n\t}\n\treturn nil\n}\n\nfunc (u *labelUseCaseImpl) AddLabels(ctx context.Context, issueID string, labels []string, actor string) error {\n\treturn u.addMany(ctx, issueID, labels, actor, false)\n}\n\nfunc (u *labelUseCaseImpl) AddWispLabels(ctx context.Context, wispID string, labels []string, actor string) error {\n\treturn u.addMany(ctx, wispID, labels, actor, true)\n}\n\nfunc (u *labelUseCaseImpl) addMany(ctx context.Context, id string, labels []string, actor string, useWisp bool) error {\n\tif id == \"\" {\n\t\treturn fmt.Errorf(\"add labels: id must not be empty\")\n\t}\n\topts := LabelOpts{UseWispsTable: useWisp}\n\tfor _, label := range labels {\n\t\tif label == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tif err := u.labelRepo.Insert(ctx, id, label, actor, opts); err != nil {\n\t\t\treturn fmt.Errorf(\"add labels: %s: %w\", label, err)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (u *labelUseCaseImpl) RemoveLabels(ctx context.Context, issueID string, labels []string, actor string) error {\n\treturn u.removeMany(ctx, issueID, labels, actor, false)\n}\n\nfunc (u *labelUseCaseImpl) RemoveWispLabels(ctx context.Context, wispID string, labels []string, actor string) error {","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/label.go#L85-L121","documentation":"Thrown by the labels use case when addMany (AddLabels / AddWispLabels) is called with an empty issue or wisp ID. The use case validates the ID up front because the repository layer cannot insert labels for a nonexistent or unidentifiable record. It is a fail-fast input validation guard, not a storage failure.","triggerScenarios":"Calling AddLabels(ctx, \"\", labels, actor) or AddWispLabels(ctx, \"\", labels, actor), or passing an ID variable that was never populated (empty string from a failed lookup, unset config field, or empty struct field).","commonSituations":"Parsing an issue key from user input that trimmed to empty; reading an ID from an unmarshaled config/JSON that omitted the field; constructing issue structs where the ID is assigned after labels are set; wiring commands where the positional argument was missing.","solutions":["Verify the issue/wisp was actually created and its ID captured before calling AddLabels","Log or print the ID immediately before the call to confirm it is non-empty","Fix the upstream code path that produced the empty ID (failed lookup, missing CLI argument, unset struct field)","If acting on a wisp, call AddWispLabels with the wisp ID rather than the issue ID"],"exampleFix":"// before\nissue, _ := store.CreateIssue(ctx, opts)\nerr := store.AddLabels(ctx, \"\", labels, actor) // empty literal\n// after\nissue, err := store.CreateIssue(ctx, opts)\nif err != nil { return err }\nif issue.ID == \"\" { return fmt.Errorf(\"no issue id\") }\nerr = store.AddLabels(ctx, issue.ID, labels, actor)","handlingStrategy":"validation","validationCode":"if id == \"\" {\n\treturn fmt.Errorf(\"cannot add labels: issue id is empty\")\n}\nif err := store.AddLabels(ctx, id, labels, actor); err != nil { ... }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always use the ID returned by CreateIssue/GetIssue, never a hand-typed placeholder","Validate IDs at system boundaries (CLI args, JSON decode) before business calls","In bulk jobs, skip records with empty IDs and log them","Distinguish issue IDs from wisp IDs and use the matching API"],"tags":["validation","labels","empty-id","input"],"backgroundTag":"empty-required-identifier","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}