{"record":{"id":"437c121f20dbad51","repo":"amir20/dozzle","slug":"invalid-maxstart","errorCode":null,"errorMessage":"invalid maxStart","messagePattern":"invalid maxStart","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"internal/web/logs.go","lineNumber":161,"sourceCode":"\t\t\thttp.Error(w, err.Error(), http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t\tif minimum < 0 || minimum > buffer.Size {\n\t\t\thttp.Error(w, \"minimum must be between 0 and buffer size\", http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t\tbuffer = utils.NewRingBuffer[*container.LogEvent](minimum)\n\t}\n\n\tmaxStart := math.MaxInt\n\tif r.URL.Query().Has(\"maxStart\") {\n\t\tmaxStart, err = strconv.Atoi(r.URL.Query().Get(\"maxStart\"))\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t\tif maxStart < 1 || maxStart > buffer.Size {\n\t\t\thttp.Error(w, \"invalid maxStart\", http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t}\n\n\tlevels := make(map[string]struct{})\n\tfor _, level := range r.URL.Query()[\"levels\"] {\n\t\tlevels[level] = struct{}{}\n\t}\n\n\tlastSeenId := uint32(0)\n\tif r.URL.Query().Has(\"lastSeenId\") {\n\t\tto = to.Add(50 * time.Millisecond)\n\t\tnum, err := strconv.ParseUint(r.URL.Query().Get(\"lastSeenId\"), 10, 32)\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t\tlastSeenId = uint32(num)","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/amir20/dozzle/blob/d9463cbe21874e44ab79db6fa63e746ca7d22928/internal/web/logs.go#L143-L179","documentation":"After parsing `maxStart`, the handler validates 1 <= maxStart <= buffer.Size (500). Out-of-range values receive the fixed message \"invalid maxStart\" with HTTP 400 Bad Request. maxStart is 1-based and must fit within the ring buffer.","triggerScenarios":"GET .../logs?maxStart=0 (below the 1-based minimum) or ?maxStart=501 (above buffer size 500). Negative values likewise fail.","commonSituations":"Clients that captured lastSeenId style indices starting at 0; sending event IDs instead of buffer indices; code assuming maxStart is 0-based; buffer resized via `min` to less than the requested maxStart.","solutions":["Use a 1-based integer between 1 and 500","Omit maxStart when unsure; the default allows any start","Derive maxStart from the buffer size of the previous response, not from container event IDs","Validate 1 <= value <= 500 before sending"],"exampleFix":"// before\nparams.set(\"maxStart\", String(event.id)); // id may be 0 or huge\n// after\nif (idx >= 1 && idx <= 500) params.set(\"maxStart\", String(idx));","handlingStrategy":"validation","validationCode":"if (!Number.isInteger(v) || v < 1 || v > 500) throw new Error(\"maxStart out of range\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remember maxStart is 1-based","Derive values from prior buffer metadata, not event ids","Omit the parameter when the semantics are unclear"],"tags":["http","query-parameter","bad-request","value-out-of-range"],"backgroundTag":"value-out-of-range","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"}