amir20/dozzle · error
invalid image reference
Error message
invalid image reference %q: empty digest
What it means
When the reference contains '@', everything after it is the digest; if it is empty (reference ends with '@'), ParseReference returns this error because a digest-qualified reference must carry a digest value.
Solutions
- Remove the trailing '@' if you did not intend digest pinning
- Provide the full digest, e.g. nginx:1.25@sha256:<64 hex chars>
- Guard the string building code so the digest is only appended when non-empty
Example fix
// before
ref := "nginx:1.25@" + digest // digest may be ""
// after
var ref string
if digest != "" {
ref = "nginx:1.25@" + digest
} else {
ref = "nginx:1.25"
} Defensive patterns
Strategy: validation
Validate before calling
if strings.HasSuffix(ref, "@") {
return fmt.Errorf("reference %q ends with '@' but has no digest", ref)
} Type guard
func isDigestPinned(ref string) bool {
i := strings.Index(ref, "@")
return i != -1 && i < len(ref)-1
} Try / catch
if _, err := imagecheck.ParseReference(ref); err != nil {
if strings.Contains(err.Error(), "empty digest") {
ref = strings.TrimSuffix(ref, "@")
}
} Prevention
- Only append '@' + digest when the digest is non-empty
- Prefer tag-pinned references unless you truly digest-pin
- Validate image strings at config load time
When it happens
Trigger: Passing references like "nginx@", "nginx:1.25@", or "repo:5000/img@" where the '@' delimiter exists but nothing follows it.
Common situations: String concatenation that appends '@' plus a digest fetched asynchronously but failed, templates that render '@{{digest}}' as bare '@', copy-paste truncation of a digest-pinned image name.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- empty image reference
- invalid image reference
- invalid image reference
- Failed to save alert
- Toast id is required when once is true
AI-assisted analysis of amir20/dozzle@d9463cbe21 (2026-09-07).
Data as JSON: /api/errors/30d7c01b17cd6ae7.
Report an issue: GitHub.
Appendix: source
Thrown at internal/imagecheck/reference.go:101
return fmt.Sprintf("%s://%s/v2/%s/manifests/%s", r.scheme(), r.host(), r.Repository, target)
}
// ParseReference splits an image reference into its registry, repository and
// tag/digest parts, applying Docker's implicit defaults.
func ParseReference(ref string) (Reference, error) {
if ref == "" {
return Reference{}, fmt.Errorf("empty image reference")
}
remainder := ref
var digest string
// A digest always trails the reference and may follow a tag, as in
// "nginx:1.25@sha256:abc...".
if i := strings.Index(remainder, "@"); i != -1 {
digest = remainder[i+1:]
remainder = remainder[:i]
if digest == "" {
return Reference{}, fmt.Errorf("invalid image reference %q: empty digest", ref)
}
}
registry := defaultRegistry
// The first path component is a registry only when it looks like a host:
// it contains a dot or port separator, or is localhost. Otherwise it is a
// Docker Hub namespace such as "amir20" in "amir20/dozzle".
if i := strings.Index(remainder, "/"); i != -1 {
candidate := remainder[:i]
if candidate == "localhost" || strings.ContainsAny(candidate, ".:") {
registry = candidate
remainder = remainder[i+1:]
}
}
// Docker Hub answers to several names. They have to collapse to one, or a
// reference written as index.docker.io/library/nginx never lines up with
// the "nginx@sha256:..." that Docker records locally.View on GitHub (pinned to d9463cbe21)