gastownhall/beads · error

external reference missing capability name

Error message

external reference missing capability name

What it means

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.

Source

Thrown at cmd/bd/dep.go:1505

// Valid format: external:<project>:<capability>
func validateExternalRef(ref string) error {
	if !strings.HasPrefix(ref, "external:") {
		return fmt.Errorf("external reference must start with 'external:'")
	}

	parts := strings.SplitN(ref, ":", 3)
	if len(parts) != 3 {
		return fmt.Errorf("invalid external reference format: expected 'external:<project>:<capability>', got '%s'", ref)
	}

	project := parts[1]
	capability := parts[2]

	if project == "" {
		return fmt.Errorf("external reference missing project name")
	}
	if capability == "" {
		return fmt.Errorf("external reference missing capability name")
	}

	return nil
}

// IsExternalRef returns true if the dependency reference is an external reference.
func IsExternalRef(ref string) bool {
	return strings.HasPrefix(ref, "external:")
}

// ParseExternalRef parses an external reference into project and capability.
// Returns empty strings if the format is invalid.
func ParseExternalRef(ref string) (project, capability string) {
	if !IsExternalRef(ref) {
		return "", ""
	}
	parts := strings.SplitN(ref, ":", 3)
	if len(parts) != 3 {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Append the capability name: external:<project>:<capability>, e.g. external:myproject:deploy.
  2. Fix the template/variable so the capability segment is populated before the dep add call.
  3. Validate the ref with a quick shell check: case "$ref" in external:*:??*) ok;; *) fail;; esac.

Example fix

// before
bd dep add bd-1 "external:myproject:${CAPABILITY}"  # CAPABILITY empty

// after
: "${CAPABILITY:?CAPABILITY must be set}"
bd dep add bd-1 "external:myproject:${CAPABILITY}"
Defensive patterns

Strategy: validation

Validate before calling

func hasCapabilitySegment(ref string) bool {
	parts := strings.SplitN(strings.TrimPrefix(ref, "external:"), ":", 3)
	return len(parts) == 3 && strings.TrimSpace(parts[1]) != ""
}

Try / catch

if err := validateExternalRef(ref); err != nil {
	if strings.Contains(err.Error(), "missing capability name") {
		return fmt.Errorf("append :<capability> to external ref %q", ref)
	}
	return err
}

Prevention

When it happens

Trigger: Supplying 'external:myproject:' — prefix and project present but capability empty; also produced when a variable feeding the capability is unset.

Common situations: Script templating with an empty $CAPABILITY; truncation when appending to the ref; authors assuming the capability is optional and writing only external:project:.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/8fe2f4dde7d3de8c. Report an issue: GitHub.