amir20/dozzle · warning

err.Error()

Error message

err.Error()

What it means

downloadLogs returns a 400 with the regex parse error when the `filter` query parameter cannot be compiled as a regular expression. support_web.ParseRegex wraps regexp.Compile, so any syntactically invalid Go RE2 pattern (unbalanced parens, bad escape sequences, invalid character classes) is rejected before any container lookup happens.

Solutions

  1. Validate the filter pattern with regexp.Compile before building the download URL.
  2. URL-encode the filter parameter (encodeURIComponent / url.QueryEscape) so metacharacters survive transport.
  3. Fall back to no filter if the pattern fails to compile.

Example fix

// before
const url = `/api/hosts/${host}/containers/${id}/download?filter=${userInput}`
// after
const re = new RegExp(userInput) // or regexp.Compile server-side
if (!isValidGoRegex(userInput)) throw new Error('invalid filter regex')
const url = `/api/hosts/${host}/containers/${id}/download?filter=${encodeURIComponent(userInput)}`
Defensive patterns

Strategy: validation

Validate before calling

function isValidGoRegex(p) {
  try { new RegExp(p); return p.indexOf('\\') === -1 || !/\\[QEHAGKZR]/.test(p); } catch { return false; }
}
if (!isValidGoRegex(filter)) throw new Error(`invalid filter regex: ${filter}`)

Prevention

When it happens

Trigger: GET /api/hosts/{host}/containers/{id}/download with a query like ?filter=([a-] or ?filter=\Q, i.e. any filter string that fails regexp.Compile.

Common situations: Users hand-crafting filter URLs; UI escaping bugs where user search input is placed raw into the query string; patterns copied from PCRE-flavored tools that use RE2-unsupported or invalid syntax.

Related errors


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

Appendix: source

Thrown at internal/web/download.go:66

	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
	levels := make(map[string]struct{})
	if r.URL.Query().Has("levels") {
		for _, level := range r.URL.Query()["levels"] {
			levels[level] = struct{}{}
		}
	}

	// Validate all containers before starting to write response
	type containerInfo struct {
		hostId           string

View on GitHub (pinned to d9463cbe21)