{"record":{"id":"0c8e044c3242b303","repo":"amir20/dozzle","slug":"stdout-or-stderr-is-required","errorCode":null,"errorMessage":"stdout or stderr is required","messagePattern":"stdout or stderr is required","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"internal/web/download.go","lineNumber":56,"sourceCode":"\tif !permit {\n\t\tlog.Warn().Msg(\"user is not permitted to download logs from container\")\n\t\thttp.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)\n\t\treturn\n\t}\n\n\tnow := time.Now()\n\tnowFmt := now.Format(\"2006-01-02T15-04-05\")\n\n\tvar stdTypes container.StdType\n\tif r.URL.Query().Has(\"stdout\") {\n\t\tstdTypes |= container.STDOUT\n\t}\n\tif r.URL.Query().Has(\"stderr\") {\n\t\tstdTypes |= container.STDERR\n\t}\n\n\tif stdTypes == 0 {\n\t\thttp.Error(w, \"stdout or stderr is required\", http.StatusBadRequest)\n\t\treturn\n\t}\n\n\t// Parse filter regex if provided\n\tvar regex *regexp.Regexp\n\tvar err error\n\tif r.URL.Query().Has(\"filter\") {\n\t\tregex, err = support_web.ParseRegex(r.URL.Query().Get(\"filter\"))\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t}\n\n\t// Inverse mode excludes lines matching the regex instead of keeping them.\n\tinverse := r.URL.Query().Get(\"inverse\") == \"true\"\n\n\t// Parse level filters if provided","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/amir20/dozzle/blob/d9463cbe21874e44ab79db6fa63e746ca7d22928/internal/web/download.go#L38-L74","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Add ?stdout=true to the download URL (or stderr=true, or both).","Check the frontend download builder to ensure at least one stream checkbox is checked before requesting.","Verify flag names are lowercase `stdout`/`stderr` as expected by the handler."],"exampleFix":"// before\n/api/hosts/local/logs/download\n// after\n/api/hosts/local/logs/download?stdout=true&stderr=true","handlingStrategy":"validation","validationCode":"const params = new URLSearchParams();\nif (stdout) params.set('stdout', 'true');\nif (stderr) params.set('stderr', 'true');\nif (![...params.keys()].length) return; // nothing selected, don't request","typeGuard":"function hasStreamSelection(s: { stdout: boolean; stderr: boolean }): boolean {\n  return s.stdout || s.stderr;\n}","tryCatchPattern":null,"preventionTips":["Disable the download action until at least one stream type is selected.","Always append ?stdout=true (or stderr) when constructing download URLs manually.","Use lowercase flag names exactly as the API expects."],"tags":["http-400","query-parameter","download"],"backgroundTag":"missing-required-argument","analyzedSha":"d9463cbe21874e44ab79db6fa63e746ca7d22928","analyzedAt":"2026-09-07T10:08:55.855Z","contentChangedAt":"2026-09-07T10:08:55.855Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}