amir20/dozzle · info · ErrAuthRequired
registry requires authentication
Error message
registry requires authentication
What it means
ErrAuthRequired means the container image registry rejected an anonymous request during an update check. Dozzle has no credential store, so it cannot authenticate to private registries; instead of retrying endlessly it surfaces this sentinel so the checker can report the image as 'auth required' rather than treating it as a transient failure.
Solutions
- Verify the image is publicly pullable: docker manifest inspect <image> (or curl the registry v2 manifest endpoint) without credentials.
- If the image is private, accept the StatusAuthRequired status in the update-check result or stop watching that image; Dozzle will not check updates for it.
- Pull the image locally with proper docker login so the local digest exists; Dozzle can still compare against the locally available digest.
- If 401 is coming from Docker Hub rate limiting rather than a truly private image, wait out the rate window or use a registry mirror/proxy.
Defensive patterns
Strategy: try-catch
Validate before calling
// before relying on update checks docker manifest inspect <image:tag> >/dev/null 2>&1 || echo 'not anonymously pullable'
Type guard
func isAuthRequired(err error) bool { return errors.Is(err, imagecheck.ErrAuthRequired) } Try / catch
if err != nil {
if errors.Is(err, imagecheck.ErrAuthRequired) {
// report StatusAuthRequired; do NOT shorten TTL or retry
result.Status = StatusAuthRequired
} else { /* transient: retry with backoff */ }
} Prevention
- Only watch images that are publicly pullable
- Check the update-check result status for StatusAuthRequired and skip retries for it
- Remember Dozzle has no credential store — pre-pull private images yourself
- Treat this as permanent, not transient: it intentionally keeps the full TTL
When it happens
Trigger: remoteDigest/Digest makes a manifest request without credentials and the registry answers 401 (or a token request is denied); Check and Digest propagate it, and checker.go maps it to StatusAuthRequired while deliberately NOT shortening the cache TTL (checker.go:290).
Common situations: Watching a private image (e.g. a paid or GHCR private package) whose tag cannot be read anonymously; Docker Hub rate-limit-style 401s for unauthenticated pulls; pulling images from a registry that requires a token even for manifest HEAD requests.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- image not found in registry
- registry rate limited the request
- invalid credentials
- container not found
- unknown error: with
AI-assisted analysis of amir20/dozzle@d9463cbe21 (2026-09-07).
Data as JSON: /api/errors/ce4070494fd0f888.
Report an issue: GitHub.
Appendix: source
Thrown at internal/imagecheck/registry.go:31
"github.com/rs/zerolog/log"
)
// acceptManifests lists every manifest media type we are willing to receive.
// Multi-arch images resolve to an index/manifest-list, which is the digest
// recorded in the local RepoDigests, so those come first.
var acceptManifests = strings.Join([]string{
"application/vnd.oci.image.index.v1+json",
"application/vnd.docker.distribution.manifest.list.v2+json",
"application/vnd.docker.distribution.manifest.v2+json",
"application/vnd.oci.image.manifest.v1+json",
}, ",")
var (
// ErrAuthRequired means the registry rejected an anonymous request. Dozzle
// has no credential store, so private images are reported rather than
// retried.
ErrAuthRequired = errors.New("registry requires authentication")
// ErrNotFound means the tag no longer exists upstream.
ErrNotFound = errors.New("image not found in registry")
// ErrRateLimited means the registry asked us to back off.
ErrRateLimited = errors.New("registry rate limited the request")
)
type cachedToken struct {
token string
expiresAt time.Time
}
// Registry resolves the current manifest digest for an image reference using
// HEAD requests, which registries do not count against image pull rate limits.
type Registry struct {
client *http.Client
mu sync.Mutex
tokens map[string]cachedTokenView on GitHub (pinned to d9463cbe21)