gastownhall/beads · error
oci:// URL must include a namespace or bucket host
Error message
oci:// URL must include a namespace or bucket host
What it means
oci:// URLs must include a namespace or bucket host (e.g. oci://namespace/bucket/path). An empty parsed.Host means the registry namespace/bucket portion is missing, so the object store location is unresolvable.
Source
Thrown at internal/remotecache/url.go:166
return fmt.Errorf("%s:// URL must include a hostname", scheme)
}
case "ssh", "git", "git+ssh":
if parsed.Host == "" {
return fmt.Errorf("%s:// URL must include a hostname", scheme)
}
case "s3", "aws", "gs":
// s3://bucket/path, aws://bucket/path, gs://bucket/path — host is the bucket
if parsed.Host == "" {
return fmt.Errorf("%s:// URL must include a bucket name", scheme)
}
case "az":
// az://account.blob.core.windows.net/container/path
if parsed.Host == "" {
return fmt.Errorf("az:// URL must include a storage account hostname")
}
case "oci":
if parsed.Host == "" {
return fmt.Errorf("oci:// URL must include a namespace or bucket host")
}
case "file":
// file:// is allowed with any path
case "git+file":
// git+file:// is Dolt's normalized form for local git remotes.
}
return nil
}
// validateSCPURL validates an SCP-style URL (user@host:path)
func validateSCPURL(rawURL string) error {
// Already matched gitSSHPattern, so structure is valid.
// Extract host and verify no control chars (already checked above).
atIdx := strings.Index(rawURL, "@")
colonIdx := strings.Index(rawURL[atIdx:], ":")
if atIdx < 0 || colonIdx < 0 {
return fmt.Errorf("SCP-style URL must be in user@host:path format")View on GitHub (pinned to 71377f2769)
Solutions
- Add the namespace/bucket host: "oci://my-namespace/my-bucket/path"
- Check OCI_NAMESPACE / bucket config substitution is non-empty
- Match the object-storage layout used by your OCI provider (namespace first, then bucket)
Example fix
// before remote := "oci:///my-bucket/db" // after remote := "oci://my-namespace/my-bucket/db"
Defensive patterns
Strategy: validation
Validate before calling
func validOCIURL(u string) bool {
rest, ok := strings.CutPrefix(u, "oci://")
if !ok { return false }
host := rest
if i := strings.Index(rest, "/"); i >= 0 { host = rest[:i] }
return host != ""
} Type guard
func ociURLWithNamespace(s string) (ns string, ok bool) {
rest, has := strings.CutPrefix(s, "oci://")
if !has { return "", false }
if i := strings.Index(rest, "/"); i >= 0 { rest = rest[:i] }
return rest, rest != ""
} Try / catch
if err := remotecache.ValidateRemoteURL(u); err != nil {
if strings.Contains(err.Error(), "namespace or bucket host") {
return fmt.Errorf("oci remote %q must be oci://namespace/bucket/path", u)
}
} Prevention
- Format as fmt.Sprintf("oci://%s/%s/%s", namespace, bucket, path) with namespace checked non-empty
- Check OCI namespace config at startup
- Add a builder function instead of string concatenation at call sites
When it happens
Trigger: ValidateRemoteURL with "oci://", "oci:///bucket/path", or a URL missing the namespace host segment.
Common situations: OCI remotes built from templates where the NAMESPACE variable was empty, or copying only the object path from a cloud console URL.
Related errors
- %s:// URL must include a bucket name
- remote URL has no scheme (expected one of: %s)
- remote URL scheme %q is not allowed (expected one of: %s)
- dolthub:// URL must have org/repo format (e.g., dolthub://my
- %s:// URL must include a hostname
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/511b4b8a510813a2.
Report an issue: GitHub.