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
- Remove leading/trailing/duplicate slashes so the value is exactly "owner/repo" or "host/owner/repo".
- Fix template variables that were empty at render time (e.g. ensure host is set or dropped).
- Re-check what produced the value: URL join logic or string concatenation that injects empty segments.
- 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
- Trim leading/trailing slashes from user input before storing.
- Guard string concatenation/templates that build repo paths (check for empty segments).
- Normalize "$host/$owner/$repo" style templates: drop empty variables entirely.
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
- repo %q must use OWNER/REPO or HOST/OWNER/REPO
- repo %q contains invalid character %q
- identity: invalid proxy secret
- backend must be set
- invalid repo metadata: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/3a408acfbc8b6eb7.
Report an issue: GitHub.