{"record":{"id":"80da54ee3d9e2ab6","repo":"gastownhall/beads","slug":"deps-target-is-empty","errorCode":null,"errorMessage":"--deps target is empty","messagePattern":"--deps target is empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/create_deps.go","lineNumber":115,"sourceCode":"}\n\n// resolveDepSpecTargets rewrites each non-external TargetID through the same\n// partial-ID resolution path as `bd dep add` (utils.ResolvePartialID).\n//\n// Without this, `bd create --deps discovered-from:8vezf` stores the bare\n// token as depends_on_id, producing a dangling edge that `bd dep list` cannot\n// see and that `bd dep remove … 8vezf` then mis-targets after resolving the\n// good fully-qualified row (GH#5005).\nfunc resolveDepSpecTargets(ctx context.Context, st storage.Storage, specs []domain.DependencySpec) ([]domain.DependencySpec, error) {\n\tif len(specs) == 0 {\n\t\treturn specs, nil\n\t}\n\tout := make([]domain.DependencySpec, len(specs))\n\tfor i, spec := range specs {\n\t\tout[i] = spec\n\t\ttarget := strings.TrimSpace(spec.TargetID)\n\t\tif target == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"--deps target is empty\")\n\t\t}\n\t\tif strings.HasPrefix(target, \"external:\") {\n\t\t\tout[i].TargetID = target\n\t\t\tcontinue\n\t\t}\n\t\tresolved, err := utils.ResolvePartialID(ctx, st, target)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"resolving --deps target %q: %w\", target, err)\n\t\t}\n\t\tout[i].TargetID = resolved\n\t}\n\treturn out, nil\n}\n\nfunc parseDepSpec(raw string) (domain.DependencySpec, error) {\n\tif !strings.Contains(raw, \":\") {\n\t\treturn domain.DependencySpec{\n\t\t\tType:     types.DepBlocks,","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/create_deps.go#L97-L133","documentation":"resolveDepSpecTargets validates every --deps spec's TargetID after whitespace trimming; an empty target (e.g. \"blocks:\" or an empty list element \",\") yields this error. Empty targets can never resolve to an issue, so the CLI fails fast before any ID resolution or DB write.","triggerScenarios":"`bd create ... --deps \"blocks:\"` (colon with no id), `--deps \"bd-1,,bd-2\"` (empty element from double comma), or `--deps \",\"` / trailing-comma style inputs parsed by parseDepSpecs into a spec with TargetID=\"\".","commonSituations":"Shell scripts building the deps string with variables that are unset/empty (e.g. `--deps \"blocks:$DEP_ID\"` with $DEP_ID empty); copy-pasted lists with stray commas.","solutions":["Fix the --deps argument so every spec has a non-empty target after the colon","In scripts, guard the variable: skip the flag entirely if the dep ID variable is empty","Trim and split the list before passing it, dropping empty segments"],"exampleFix":"// before\nbd create \"Task\" --deps \"blocks:$DEP_ID\"   # DEP_ID empty -> '--deps target is empty'\n// after\nif [ -n \"$DEP_ID\" ]; then\n  bd create \"Task\" --deps \"blocks:$DEP_ID\"\nfi","handlingStrategy":"validation","validationCode":"parts := strings.Split(depsFlag, \",\")\nfor _, p := range parts {\n    if strings.TrimSpace(strings.TrimPrefix(strings.TrimSpace(p), \"\")) == \"\" || strings.HasSuffix(strings.TrimSpace(p), \":\") {\n        return fmt.Errorf(\"empty --deps entry: %q\", p)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Guard shell variables: only add --deps when the dep ID is non-empty","Trim and filter empty segments before joining the list","Avoid trailing/double commas in generated lists"],"tags":["cli","dependencies","validation","empty-argument"],"backgroundTag":"empty-dependency-target","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}