{"record":{"id":"e92ef84bfb01514b","repo":"gastownhall/beads","slug":"get-labels-id-must-not-be-empty","errorCode":null,"errorMessage":"get labels: id must not be empty","messagePattern":"get labels: id must not be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/label.go","lineNumber":193,"sourceCode":"\t\t\tif err := u.labelRepo.Insert(ctx, id, l, actor, opts); err != nil {\n\t\t\t\treturn fmt.Errorf(\"set labels: add %s: %w\", l, err)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (u *labelUseCaseImpl) GetLabels(ctx context.Context, issueID string) ([]string, error) {\n\treturn u.list(ctx, issueID, false)\n}\n\nfunc (u *labelUseCaseImpl) GetWispLabels(ctx context.Context, wispID string) ([]string, error) {\n\treturn u.list(ctx, wispID, true)\n}\n\nfunc (u *labelUseCaseImpl) list(ctx context.Context, id string, useWisp bool) ([]string, error) {\n\tif id == \"\" {\n\t\treturn nil, fmt.Errorf(\"get labels: id must not be empty\")\n\t}\n\tout, err := u.labelRepo.List(ctx, id, LabelOpts{UseWispsTable: useWisp})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"get labels %s: %w\", id, err)\n\t}\n\treturn out, nil\n}\n\nfunc (u *labelUseCaseImpl) GetLabelsForIssues(ctx context.Context, issueIDs []string) (map[string][]string, error) {\n\treturn u.listBulk(ctx, issueIDs, false)\n}\n\nfunc (u *labelUseCaseImpl) GetLabelsForWisps(ctx context.Context, wispIDs []string) (map[string][]string, error) {\n\treturn u.listBulk(ctx, wispIDs, true)\n}\n\nfunc (u *labelUseCaseImpl) listBulk(ctx context.Context, ids []string, useWisp bool) (map[string][]string, error) {\n\tif len(ids) == 0 {","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/label.go#L175-L211","documentation":"Returned by list (GetLabels / GetWispLabels) when the ID is empty. The use case rejects empty IDs before querying the repository. Note the error for a valid-but-failing read uses a slightly different format ('get labels %s'), so this exact message always means the ID string itself was empty.","triggerScenarios":"GetLabels(ctx, \"\") or GetWispLabels(ctx, \"\"); reading IDs from JSON/YAML where the field was omitted; calling before an issue was created and its ID captured.","commonSituations":"Template generators rendering label views for unset IDs; dashboards iterating over records where some entries lack IDs; wiring mistakes passing the wrong struct field.","solutions":["Verify the ID was captured from CreateIssue/lookup before calling GetLabels","Guard with a non-empty check and skip or error per record","Fix the upstream producer of the empty ID","Use GetWispLabels for wisps, passing the wisp ID"],"exampleFix":"// before\nlabels, _ := store.GetLabels(ctx, record.ID) // record.ID empty\n// after\nif record.ID == \"\" { continue }\nlabels, err := store.GetLabels(ctx, record.ID)","handlingStrategy":"validation","validationCode":"if id == \"\" {\n\treturn nil, fmt.Errorf(\"cannot get labels: id is empty\")\n}\nlabels, err := store.GetLabels(ctx, id)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check ID non-empty before label reads, especially in template/dashboard loops","Skip or log records lacking IDs in bulk reporting","Capture IDs at creation time and propagate them explicitly","Use GetWispLabels for wisps"],"tags":["validation","labels","empty-id"],"backgroundTag":"empty-required-identifier","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}