{"record":{"id":"3b1c58f14c1210ed","repo":"router-for-me/CLIProxyAPI","slug":"invalid-request-body","errorCode":null,"errorMessage":"invalid request body","messagePattern":"invalid request body","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"internal/api/handlers/management/auth_files_crud.go","lineNumber":306,"sourceCode":"\t}\n\n\tbody, err := io.ReadAll(c.Request.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read body\")\n\t}\n\tbody = bytes.TrimSpace(body)\n\tif len(body) == 0 {\n\t\treturn nil, nil\n\t}\n\n\tvar objectBody struct {\n\t\tName  string   `json:\"name\"`\n\t\tNames []string `json:\"names\"`\n\t}\n\tif body[0] == '[' {\n\t\tvar arrayBody []string\n\t\tif err := json.Unmarshal(body, &arrayBody); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid request body\")\n\t\t}\n\t\treturn uniqueAuthFileNames(arrayBody), nil\n\t}\n\tif err := json.Unmarshal(body, &objectBody); err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid request body\")\n\t}\n\n\tout := make([]string, 0, len(objectBody.Names)+1)\n\tif strings.TrimSpace(objectBody.Name) != \"\" {\n\t\tout = append(out, objectBody.Name)\n\t}\n\tout = append(out, objectBody.Names...)\n\treturn uniqueAuthFileNames(out), nil\n}\n\nfunc uniqueAuthFileNames(names []string) []string {\n\tif len(names) == 0 {\n\t\treturn nil","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/api/handlers/management/auth_files_crud.go#L288-L324","documentation":"When the delete-request body starts with `[`, it is parsed as a JSON array of file names. If json.Unmarshal fails, the handler returns `invalid request body` (array branch, auth_files_crud.go:306). The body was read fine but is not a valid JSON array of strings — e.g. trailing commas, quoted-but-object content, or array elements of the wrong type.","triggerScenarios":"DELETE body like `[\"a.json\",]` (trailing comma), `[1,2]` (non-string elements), `[\"a.json\"` (truncated JSON), or a body beginning with whitespace-stripped `[` that is actually malformed text.","commonSituations":"Hand-built curl bodies with typos; scripts joining names with trailing separators; JSON5-style input from LLM-generated commands.","solutions":["Validate the array JSON with jq before sending: jq -c '.[0]' <<< body should succeed.","Send names via query params (?name=a&name=b) to skip body parsing entirely.","Use an object body {\"names\":[...]} which is also accepted."],"exampleFix":"# before\n$ curl -X DELETE .../auth-files -d '[\"a.json\",]'\n\n# after\n$ curl -X DELETE .../auth-files -d '[\"a.json\"]'\n# or\n$ curl -X DELETE '.../auth-files?name=a.json'","handlingStrategy":"validation","validationCode":"// Validate the array body client-side before sending\nfunc validNamesArray(body []byte) bool {\n    var names []string\n    return json.Unmarshal(body, &names) == nil\n}","typeGuard":"func isInvalidRequestBody(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"invalid request body\")\n}","tryCatchPattern":"if isInvalidRequestBody(err) {\n    names := extractNames()\n    err = deleteViaQueryParams(names) // bypass body parsing entirely\n}","preventionTips":["Validate delete bodies with jq before sending.","Use query params or the {\"names\":[...]} object form as more robust alternatives.","Never hand-type JSON arrays in shell without quoting checks."],"tags":["management-api","json","validation","request-body"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}