router-for-me/CLIProxyAPI · error
must be a positive integer
Error message
must be a positive integer
What it means
Returned by parseLimit (logs.go:1224) when the `limit` query parameter of a management log endpoint is non-empty but not parseable by strconv.Atoi. The parameter must be a base-10 integer; floats, suffixed numbers, or arbitrary strings are rejected before any log reading happens.
Source
Thrown at internal/api/handlers/management/logs.go:1224
value := strings.TrimSpace(raw)
if value == "" {
return 0
}
ts, err := strconv.ParseInt(value, 10, 64)
if err != nil || ts <= 0 {
return 0
}
return ts
}
func parseLimit(raw string) (int, error) {
value := strings.TrimSpace(raw)
if value == "" {
return 0, nil
}
limit, err := strconv.Atoi(value)
if err != nil {
return 0, fmt.Errorf("must be a positive integer")
}
if limit <= 0 {
return 0, fmt.Errorf("must be greater than zero")
}
return limit, nil
}
func parseTimestamp(line string) int64 {
if strings.HasPrefix(line, "[") {
line = line[1:]
}
if len(line) < 19 {
return 0
}
candidate := line[:19]
t, err := time.ParseInLocation("2006-01-02 15:04:05", candidate, time.Local)
if err != nil {
return 0View on GitHub (pinned to 78f0c4079e)
Solutions
- Send a plain integer: /management/logs?limit=100
- Omit the parameter entirely if you want the server default (empty string is accepted as no limit)
- Fix the client to validate limit is an integer before building the URL
Example fix
# before curl -H "Authorization: Bearer $KEY" 'http://127.0.0.1:8000/management/logs?limit=10.5' # after curl -H "Authorization: Bearer $KEY" 'http://127.0.0.1:8000/management/logs?limit=10'
Defensive patterns
Strategy: validation
Validate before calling
// Client-side guard before building the URL.
if limitParam != "" {
if _, err := strconv.Atoi(strings.TrimSpace(limitParam)); err != nil {
limitParam = "" // drop invalid value, use server default
}
} Type guard
function isValidLimit(raw string) bool {
if strings.TrimSpace(raw) === "") return true;
return /^-?\d+$/.test(raw.trim()) && parseInt(raw.trim(), 10) > 0;
} Prevention
- Always send limit as a plain base-10 integer
- Map UI concepts like 'all' to omitting the parameter, not to a keyword
- Beware locale formatting (commas) when interpolating numbers into URLs
When it happens
Trigger: GET /management/logs?limit=10.5, ?limit=all, ?limit=1e3, or a limit containing whitespace/signs that Atoi rejects. Any log-reading endpoint that accepts `limit` funnels through parseLimit (logs.go:78).
Common situations: Dashboards sending UI defaults like 'all' or 'None' as limit; copy-pasted URLs with locale-formatted numbers (1,000); query builders that serialize floats as strings.
Related errors
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/5512a1cda47b40e1.
Report an issue: GitHub.