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

  1. Strip the hostname: use 'docker-hub: library/nginx:1.27' or just 'docker-hub: nginx:1.27'
  2. Keep at most one slash: namespace/repository, with optional :tag
  3. 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

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


AI-assisted analysis of glanceapp/glance@91324e8de7 (2026-08-15). Data as JSON: /api/errors/b9ae8d88cdbd2202. Report an issue: GitHub.