amir20/dozzle · error

err.Error()

Error message

err.Error()

What it means

After stdtypes validation, fetchLogsBetweenDates resolves the container via FindContainer(hostKey(r), id). Failure returns a 404 with err.Error(): the host is unknown/unreachable or no container matches the id.

Solutions

  1. Look up the current container id from /api/containers.json before fetching logs.
  2. Verify the host key corresponds to an existing, connected host.
  3. For recreated containers, re-resolve by container name/label rather than a persisted id.

Example fix

// before
const logs = await fetch(`/api/hosts/${h}~${persistedId}/logs?from=...&to=...&stdtypes=stdout`)
// after
const c = await resolveCurrentContainer(persistedName)
const logs = await fetch(`/api/hosts/${c.host}~${c.id}/logs?from=...&to=...&stdtypes=stdout`)
Defensive patterns

Strategy: try-catch

Validate before calling

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

Try / catch

try {
  const res = await fetch(logsUrl);
  if (res.status === 404) {
    const fresh = await resolveContainerByName(name);
    return fetchLogs(fresh.host, fresh.id);
  }
} catch (e) { /* handle */ }

Prevention

When it happens

Trigger: GET the between-dates logs endpoint with a stale or wrong container id, or a host segment that does not match an available host.

Common situations: Querying historical logs for a container that was recreated (new id); host/agent offline; pods replaced in k8s producing new ids; URL shared from a different deployment.

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/43143f265456dea1. Report an issue: GitHub.

Appendix: source

Thrown at internal/web/logs.go:114

	if plainText {
		w.Header().Set("Content-Type", "text/plain; charset=UTF-8")
	} else {
		w.Header().Set("Content-Type", "application/x-jsonl; charset=UTF-8")
	}

	from, _ := time.Parse(time.RFC3339Nano, r.URL.Query().Get("from"))
	to, _ := time.Parse(time.RFC3339Nano, r.URL.Query().Get("to"))
	id := chi.URLParam(r, "id")

	stdTypes := parseStdTypes(r)
	if stdTypes == 0 {
		http.Error(w, "stdout or stderr is required", http.StatusBadRequest)
		return
	}

	containerService, err := h.hostService.FindContainer(hostKey(r), id, h.resolveLabels(r))
	if err != nil {
		http.Error(w, err.Error(), http.StatusNotFound)
		return
	}

	delta := max(to.Sub(from), time.Second*3)

	var regex *regexp.Regexp
	if r.URL.Query().Has("filter") {
		regex, err = support_web.ParseRegex(r.URL.Query().Get("filter"))
		if err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
	}

	inverse := r.URL.Query().Get("inverse") == "true"

	onlyComplex := r.URL.Query().Has("jsonOnly")
	everything := r.URL.Query().Has("everything")

View on GitHub (pinned to d9463cbe21)