glanceapp/glance · error
invalid repository name: %s
Error message
invalid repository name: %s
What it means
Returned by fetchLatestDockerHubRelease (internal/glance/widget-releases.go:279) when the configured Docker Hub repository string splits on '/' into more than 2 parts. Docker Hub names are at most namespace/repository (e.g. library/nginx); a string like 'docker.io/library/nginx:latest' or 'registry.example.com/team/app' yields 3+ parts and is rejected before any HTTP call. Single-part names ('nginx') are auto-prefixed with the library namespace.
Source
Thrown at internal/glance/widget-releases.go:279
type dockerHubRepositoryTagsResponse struct {
Results []dockerHubRepositoryTagResponse `json:"results"`
}
type dockerHubRepositoryTagResponse struct {
Name string `json:"name"`
LastPushed string `json:"tag_last_pushed"`
}
const dockerHubOfficialRepoTagURLFormat = "https://hub.docker.com/_/%s/tags?name=%s"
const dockerHubRepoTagURLFormat = "https://hub.docker.com/r/%s/tags?name=%s"
const dockerHubTagsURLFormat = "https://hub.docker.com/v2/namespaces/%s/repositories/%s/tags"
const dockerHubSpecificTagURLFormat = "https://hub.docker.com/v2/namespaces/%s/repositories/%s/tags/%s"
func fetchLatestDockerHubRelease(request *releaseRequest) (*appRelease, error) {
nameParts := strings.Split(request.Repository, "/")
if len(nameParts) > 2 {
return nil, fmt.Errorf("invalid repository name: %s", request.Repository)
} else if len(nameParts) == 1 {
nameParts = []string{"library", nameParts[0]}
}
tagParts := strings.SplitN(nameParts[1], ":", 2)
var requestURL string
if len(tagParts) == 2 {
requestURL = fmt.Sprintf(dockerHubSpecificTagURLFormat, nameParts[0], tagParts[0], tagParts[1])
} else {
requestURL = fmt.Sprintf(dockerHubTagsURLFormat, nameParts[0], nameParts[1])
}
httpRequest, err := http.NewRequest("GET", requestURL, nil)
if err != nil {
return nil, err
}
View on GitHub (pinned to 91324e8de7)
Solutions
- Strip the hostname: use 'docker-hub: library/nginx:1.27' or just 'docker-hub: nginx:1.27'
- Keep at most one slash: namespace/repository, with optional :tag
- For images on other registries, this widget cannot track them — use a different mechanism
Example fix
// before (glance.yml) - docker-hub: docker.io/library/postgres:16 // after - docker-hub: postgres:16 // or - docker-hub: library/postgres:16
Defensive patterns
Strategy: validation
Validate before calling
// Validate a Docker Hub image reference before configuring
parts := strings.Split(repo, "/")
if len(parts) > 2 {
// strip hostname: use last two segments, or reject private registries
} Try / catch
if err != nil && strings.Contains(err.Error(), "invalid repository name") {
// strip registry hostname from the config entry
} Prevention
- Configure bare namespace/repo[:tag], never registry hostnames
- Docker Hub only — other registries are unsupported
- Single-name images are auto-prefixed with library/
When it happens
Trigger: Configuring 'docker-hub: docker.io/library/nginx:1.27' (hostname included), 'docker-hub: registry.corp.io/team/app', or a typo adding extra slashes ('user//repo'). Only bare 'namespace/repo[:tag]' or 'repo[:tag]' forms are accepted.
Common situations: Copy-pasting the full image reference from a docker pull command or docker-compose file into the widget config; assuming the widget accepts registry hostnames; private-registry images (not supported — this widget is Docker Hub only).
Related errors
- repository is required
- invalid source
- could not umarshal repository into string or struct: %v
- URL is required
- nested groups are not supported
AI-assisted analysis of glanceapp/glance@91324e8de7 (2026-08-15).
Data as JSON: /api/errors/b9ae8d88cdbd2202.
Report an issue: GitHub.