router-for-me/CLIProxyAPI · warning
failed to read body
Error message
failed to read body
What it means
requestedAuthFileNamesForDelete accepts deletion targets via query params (`?name=...`) or, failing that, by reading the request body. If io.ReadAll on the body errors it returns `failed to read body` — the connection failed while reading the (optional) JSON body carrying name/names for the delete request. Note the underlying read error is deliberately dropped from the message.
Source
Thrown at internal/api/handlers/management/auth_files_crud.go:292
}
if err := h.upsertAuthRecord(ctx, auth); err != nil {
return err
}
return nil
}
func requestedAuthFileNamesForDelete(c *gin.Context) ([]string, error) {
if c == nil {
return nil, nil
}
names := uniqueAuthFileNames(c.QueryArray("name"))
if len(names) > 0 {
return names, nil
}
body, err := io.ReadAll(c.Request.Body)
if err != nil {
return nil, fmt.Errorf("failed to read body")
}
body = bytes.TrimSpace(body)
if len(body) == 0 {
return nil, nil
}
var objectBody struct {
Name string `json:"name"`
Names []string `json:"names"`
}
if body[0] == '[' {
var arrayBody []string
if err := json.Unmarshal(body, &arrayBody); err != nil {
return nil, fmt.Errorf("invalid request body")
}
return uniqueAuthFileNames(arrayBody), nil
}
if err := json.Unmarshal(body, &objectBody); err != nil {View on GitHub (pinned to 78f0c4079e)
Solutions
- Retry the delete request — body read failures are almost always connection-level and transient.
- Prefer the query-parameter form (?name=auth.json) which needs no body at all.
- Ensure the client sends Content-Length correctly or uses no body for DELETE.
- Check for proxy/LB request timeouts between client and management API.
Example fix
# before: body-based delete that can fail mid-read
$ curl -X DELETE http://127.0.0.1:8000/v0/management/auth-files -d '{"name":"a.json"}'
# after: query-param delete, no body
$ curl -X DELETE 'http://127.0.0.1:8000/v0/management/auth-files?name=a.json' Defensive patterns
Strategy: retry
Type guard
func isBodyReadFailure(err error) bool {
return err != nil && strings.Contains(err.Error(), "failed to read body")
} Try / catch
if isBodyReadFailure(err) {
// prefer query-param delete which needs no body
err = deleteViaQueryParams(names)
} Prevention
- Prefer ?name= query parameters for DELETE calls — no body to fail.
- Ensure clients send correct Content-Length or an empty body.
- Retry once; mid-read aborts are transient.
When it happens
Trigger: DELETE request whose body transfer aborts mid-read (client disconnect, connection reset, proxy timeout); malformed chunked encoding; client sending a body with a bad Content-Length.
Common situations: REST clients that stream a body then abort; intermediary proxies resetting long-lived connections; automation retrying a DELETE while the previous socket is half-closed.
Related errors
- invalid request body
- invalid_request
- read plugin http request body: %w
- failed to read plugin management request body
- Codex live request body too large
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/396fe2bfea24f40d.
Report an issue: GitHub.