amir20/dozzle · warning

stdout or stderr is required

Error message

stdout or stderr is required

What it means

fetchLogsBetweenDates parses the stdtypes query parameter into a bitmask; when neither stdout nor stderr is requested the mask is 0 and the handler rejects the request with 400 "stdout or stderr is required" before doing any container lookup.

Solutions

  1. Pass stdtypes=stdout, stderr, or stdout%2Cstderr in the query string.
  2. Omit other unrecognized values so the mask does not come out empty.
  3. Default to requesting both streams when the caller does not care.

Example fix

// before
const url = `/api/hosts/${host}/containers/${id}/logs?from=${from}&to=${to}`
// after
const url = `/api/hosts/${host}/containers/${id}/logs?from=${from}&to=${to}&stdtypes=stdout%2Cstderr`
Defensive patterns

Strategy: validation

Validate before calling

function assertStdTypes(std) {
  const valid = ['stdout', 'stderr'];
  const parts = (std || '').split(',').filter(Boolean);
  if (parts.length === 0 || parts.some(p => !valid.includes(p))) throw new Error('stdout or stderr is required');
}
assertStdTypes(stdtypes);

Prevention

When it happens

Trigger: GET /api/hosts/{host}/containers/{id}/logs with stdtypes missing, empty, or set to an unrecognized value so parseStdTypes returns 0 (e.g. stdtypes=both or stdtypes=1 when only named values are accepted).

Common situations: Hand-built API calls omitting the parameter; scripts copying stream values from other log tools; frontend regressions dropping the query param.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at internal/web/logs.go:108

	}
	return ids
}

func (h *handler) fetchLogsBetweenDates(w http.ResponseWriter, r *http.Request) {
	plainText := strings.Contains(r.Header.Get("Accept"), "text/plain")
	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
		}

View on GitHub (pinned to d9463cbe21)