amir20/dozzle · error

err.Error()

Error message

err.Error()

What it means

checkImageUpdate returns a 404 with err.Error() when hostService.FindContainer cannot resolve the container id from hostKey(r). This mirrors the lookup failure family: bad host, unknown id, or user-label filtering excluding the container.

Solutions

  1. Re-fetch the container list and use the fresh container id.
  2. Confirm the host segment in the URL matches the container's actual host.
  3. Verify userLabels configuration is not excluding the container from lookups.

Example fix

// before
await fetch(`/api/hosts/${savedHost}~${savedId}/check-update`)
// after
const c = await findContainerByName(name)
await fetch(`/api/hosts/${c.host}~${c.id}/check-update`)
Defensive patterns

Strategy: validation

Validate before calling

const containers = await fetch('/api/containers.json').then(r => r.json());
const exists = containers.some(c => c.host === host && c.id === id);
if (!exists) throw new Error(`container ${host}~${id} not found`);

Prevention

When it happens

Trigger: GET /api/hosts/{host}/containers/{id}/check-update (or equivalent route) with a stale container id, wrong host, or a container filtered out by userLabels.

Common situations: Container recreated after upgrade (id changed); host removed from the multi-host config; checking update for a container visible under a different host than the one in the URL.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of amir20/dozzle@d9463cbe21 (2026-09-07). Data as JSON: /api/errors/51bf05ffd8a27b15. Report an issue: GitHub.

Appendix: source

Thrown at internal/web/imagecheck.go:22

	"net/http"
	"time"

	"github.com/amir20/dozzle/internal/imagecheck"
	"github.com/go-chi/chi/v5"
	"github.com/rs/zerolog/log"
)

// checkImageUpdate reports whether a newer image exists upstream for a
// container. It is deliberately not gated behind EnableActions: knowing a
// container is out of date is useful even when the user updates it themselves
// through compose. Only the update button depends on actions being enabled.
func (h *handler) checkImageUpdate(w http.ResponseWriter, r *http.Request) {
	id := chi.URLParam(r, "id")

	containerService, err := h.hostService.FindContainer(hostKey(r), id, h.resolveLabels(r))
	if err != nil {
		log.Error().Err(err).Msg("error while trying to find container")
		http.Error(w, err.Error(), http.StatusNotFound)
		return
	}

	// A forced check bypasses the digest cache and is what the explicit
	// "check now" affordance sends.
	force := r.URL.Query().Get("force") == "true"

	// In manual mode Dozzle never reaches a registry on its own. Background
	// checks are answered without egress so the frontend can stay uniform.
	if h.config.ImageCheckMode == imagecheck.ModeManual && !force {
		writeJSON(w, http.StatusOK, imagecheck.Result{
			Image:     containerService.Container.Image,
			Status:    imagecheck.StatusSkipped,
			Reason:    "image checks are set to manual",
			CheckedAt: time.Now(),
		})
		return
	}

View on GitHub (pinned to d9463cbe21)