gastownhall/beads · error

repo %q contains an empty path component

Error message

repo %q contains an empty path component

What it means

Each slash-separated component of metadata.repo must be non-empty; an empty component means the repo path has a dangling or doubled slash (e.g. "/owner/repo", "owner//repo", "owner/repo/") and cannot name a valid GitHub repository.

Source

Thrown at cmd/bd/gate.go:890

	}
	if repoValue == nil {
		return "", fmt.Errorf("metadata.repo must not be null")
	}
	repo, ok := repoValue.(string)
	if !ok {
		return "", fmt.Errorf("metadata.repo must be a string, got %T", repoValue)
	}
	if repo == "" {
		return "", nil
	}

	parts := strings.Split(repo, "/")
	if len(parts) != 2 && len(parts) != 3 {
		return "", fmt.Errorf("repo %q must use OWNER/REPO or HOST/OWNER/REPO", repo)
	}
	for _, part := range parts {
		if part == "" {
			return "", fmt.Errorf("repo %q contains an empty path component", repo)
		}
		for _, char := range part {
			if (char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z') ||
				(char >= '0' && char <= '9') || char == '-' || char == '_' || char == '.' {
				continue
			}
			return "", fmt.Errorf("repo %q contains invalid character %q", repo, char)
		}
	}

	return repo, nil
}

// isGitHubGateType returns true for gate types whose condition is checked
// against a GitHub repository (gh:run, gh:pr, and any future gh:* type).
func isGitHubGateType(gateType string) bool {
	return strings.HasPrefix(gateType, "gh:")
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Remove leading/trailing/duplicate slashes so the value is exactly "owner/repo" or "host/owner/repo".
  2. Fix template variables that were empty at render time (e.g. ensure host is set or dropped).
  3. Re-check what produced the value: URL join logic or string concatenation that injects empty segments.
  4. Validate the metadata after editing and re-run the gate check.

Example fix

// before
{"repo": "gastownhall//beads"}
// after
{"repo": "gastownhall/beads"}
Defensive patterns

Strategy: validation

Validate before calling

func repoHasEmptyComponent(repo string) bool {
    for _, p := range strings.Split(repo, "/") {
        if p == "" { return true }
    }
    return false
} // reject or strings.TrimSpace/Trim(repo, "/") before storing

Type guard

func isCleanRepoPath(s string) bool {
    parts := strings.Split(s, "/")
    for _, p := range parts { if p == "" { return false } }
    return true
}

Prevention

When it happens

Trigger: metadata.repo strings with leading, trailing, or doubled slashes split into an empty part, hitting the `if part == ""` branch in githubRepoFromIssue during gate checks.

Common situations: Trailing slash pasted from a URL; typo "owner//repo" after deleting a hostname; template substitution that left an empty segment (e.g. "$host/$owner/repo" with $host unset).

Related errors


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