gastownhall/beads · error
repo %q must use OWNER/REPO or HOST/OWNER/REPO
Error message
repo %q must use OWNER/REPO or HOST/OWNER/REPO
What it means
The `repo` string must be either "OWNER/REPO" (2 slash-separated parts) or "HOST/OWNER/REPO" (3 parts) so it can target gh CLI --repo lookups. Any other slash count (0, 1, 4+) makes the value unresolvable and triggers this error, including the original repo string in quotes.
Source
Thrown at cmd/bd/gate.go:886
var repoValue interface{}
if err := json.Unmarshal(repoRaw, &repoValue); err != nil {
return "", fmt.Errorf("metadata.repo: %w", err)
}
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 checkedView on GitHub (pinned to 71377f2769)
Solutions
- Change the value to "owner/repo", e.g. "gastownhall/beads".
- For a self-hosted GH instance use "host/owner/repo", e.g. "github.example.com/acme/api".
- Strip URL schemes/host paths: convert "https://github.com/owner/repo" to "owner/repo" (or "github.com/owner/repo" for the 3-part form).
- Re-run the gate check to confirm the repo resolves.
Example fix
// before
{"repo": "https://github.com/gastownhall/beads"}
// after
{"repo": "gastownhall/beads"} Defensive patterns
Strategy: validation
Validate before calling
func validRepoShape(repo string) bool {
parts := strings.Split(repo, "/")
return len(parts) == 2 || len(parts) == 3
}
// call before storing metadata: if !validRepoShape(repo) { ... } Type guard
func isOwnerRepoOrHostOwnerRepo(s string) bool {
n := len(strings.Split(s, "/"))
return n == 2 || n == 3
} Prevention
- Store owner/repo paths, never full URLs — strip scheme and domain first.
- Document the accepted formats (OWNER/REPO, HOST/OWNER/REPO) wherever repo is configured.
- Trim trailing slashes before persisting user input.
When it happens
Trigger: metadata.repo set to values like "myrepo", "owner" (no slash), or "https://github.com/owner/repo" (contains 3+ slashes after splitting on "/") while running gate checks that resolve the GitHub repo.
Common situations: Users pasting a full GitHub URL instead of the owner/repo path; typing just a repo name assuming a default owner; including a protocol or trailing slash in the value.
Related errors
- repo %q contains an empty path component
- 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/554c24aca32c4a3b.
Report an issue: GitHub.