{"record":{"id":"8fe2f4dde7d3de8c","repo":"gastownhall/beads","slug":"external-reference-missing-capability-name","errorCode":null,"errorMessage":"external reference missing capability name","messagePattern":"external reference missing capability name","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/dep.go","lineNumber":1505,"sourceCode":"// Valid format: external:<project>:<capability>\nfunc validateExternalRef(ref string) error {\n\tif !strings.HasPrefix(ref, \"external:\") {\n\t\treturn fmt.Errorf(\"external reference must start with 'external:'\")\n\t}\n\n\tparts := strings.SplitN(ref, \":\", 3)\n\tif len(parts) != 3 {\n\t\treturn fmt.Errorf(\"invalid external reference format: expected 'external:<project>:<capability>', got '%s'\", ref)\n\t}\n\n\tproject := parts[1]\n\tcapability := parts[2]\n\n\tif project == \"\" {\n\t\treturn fmt.Errorf(\"external reference missing project name\")\n\t}\n\tif capability == \"\" {\n\t\treturn fmt.Errorf(\"external reference missing capability name\")\n\t}\n\n\treturn nil\n}\n\n// IsExternalRef returns true if the dependency reference is an external reference.\nfunc IsExternalRef(ref string) bool {\n\treturn strings.HasPrefix(ref, \"external:\")\n}\n\n// ParseExternalRef parses an external reference into project and capability.\n// Returns empty strings if the format is invalid.\nfunc ParseExternalRef(ref string) (project, capability string) {\n\tif !IsExternalRef(ref) {\n\t\treturn \"\", \"\"\n\t}\n\tparts := strings.SplitN(ref, \":\", 3)\n\tif len(parts) != 3 {","sourceCodeStart":1487,"sourceCodeEnd":1523,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/dep.go#L1487-L1523","documentation":"validateExternalRef requires a non-empty capability segment as the third part of the ref. 'external:project:' (trailing colon, empty capability) fails with this message. The capability identifies what feature/function of the foreign project is depended upon.","triggerScenarios":"Supplying 'external:myproject:' — prefix and project present but capability empty; also produced when a variable feeding the capability is unset.","commonSituations":"Script templating with an empty $CAPABILITY; truncation when appending to the ref; authors assuming the capability is optional and writing only external:project:.","solutions":["Append the capability name: external:<project>:<capability>, e.g. external:myproject:deploy.","Fix the template/variable so the capability segment is populated before the dep add call.","Validate the ref with a quick shell check: case \"$ref\" in external:*:??*) ok;; *) fail;; esac."],"exampleFix":"// before\nbd dep add bd-1 \"external:myproject:${CAPABILITY}\"  # CAPABILITY empty\n\n// after\n: \"${CAPABILITY:?CAPABILITY must be set}\"\nbd dep add bd-1 \"external:myproject:${CAPABILITY}\"","handlingStrategy":"validation","validationCode":"func hasCapabilitySegment(ref string) bool {\n\tparts := strings.SplitN(strings.TrimPrefix(ref, \"external:\"), \":\", 3)\n\treturn len(parts) == 3 && strings.TrimSpace(parts[1]) != \"\"\n}","typeGuard":null,"tryCatchPattern":"if err := validateExternalRef(ref); err != nil {\n\tif strings.Contains(err.Error(), \"missing capability name\") {\n\t\treturn fmt.Errorf(\"append :<capability> to external ref %q\", ref)\n\t}\n\treturn err\n}","preventionTips":["Require capability in ref-builder function signatures (no zero-value default).","Use :? checks for capability variables in shell templates.","Strip trailing colons from refs generated by concatenation."],"tags":["validation","external-references","dependencies"],"backgroundTag":"invalid-reference-format","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}