amir20/dozzle · error

stdout or stderr is required

Error message

stdout or stderr is required

What it means

downloadLogs determines which stream types to export from query flags: `stdout` and/or `stderr`. If neither flag is present, stdTypes is 0 and the handler returns 400 with this message; a download must select at least one stream.

Solutions

  1. Add ?stdout=true to the download URL (or stderr=true, or both).
  2. Check the frontend download builder to ensure at least one stream checkbox is checked before requesting.
  3. Verify flag names are lowercase `stdout`/`stderr` as expected by the handler.

Example fix

// before
/api/hosts/local/logs/download
// after
/api/hosts/local/logs/download?stdout=true&stderr=true
Defensive patterns

Strategy: validation

Validate before calling

const params = new URLSearchParams();
if (stdout) params.set('stdout', 'true');
if (stderr) params.set('stderr', 'true');
if (![...params.keys()].length) return; // nothing selected, don't request

Type guard

function hasStreamSelection(s: { stdout: boolean; stderr: boolean }): boolean {
  return s.stdout || s.stderr;
}

Prevention

When it happens

Trigger: GET to the download endpoint without ?stdout=... or ?stderr=..., e.g. /api/hosts/local/logs/download with only filters but no stream flags, or flags misspelled/uppercase.

Common situations: Frontend builds the download URL without serializing stream checkboxes; user unchecks both stdout and stderr in the UI; hand-crafted curl calls omitting the flags.

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/0c8e044c3242b303. Report an issue: GitHub.

Appendix: source

Thrown at internal/web/download.go:56

	if !permit {
		log.Warn().Msg("user is not permitted to download logs from container")
		http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
		return
	}

	now := time.Now()
	nowFmt := now.Format("2006-01-02T15-04-05")

	var stdTypes container.StdType
	if r.URL.Query().Has("stdout") {
		stdTypes |= container.STDOUT
	}
	if r.URL.Query().Has("stderr") {
		stdTypes |= container.STDERR
	}

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

	// Parse filter regex if provided
	var regex *regexp.Regexp
	var err error
	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 mode excludes lines matching the regex instead of keeping them.
	inverse := r.URL.Query().Get("inverse") == "true"

	// Parse level filters if provided

View on GitHub (pinned to d9463cbe21)