plandex-ai/plandex · error
Invalid request body:
Error message
Invalid request body:
What it means
UpsertCustomModelsHandler decodes the request body into shared.ModelsInput with json.NewDecoder(r.Body).Decode. Any malformed body — invalid JSON, wrong types (e.g. string where an object/array is expected), trailing garbage, or an empty body — produces 400 'Invalid request body: <err>'. Unlike the invites marshalling errors, this one is caused by the client's payload.
Source
Thrown at app/server/handlers/models.go:34
const CustomModelsMinClientVersion = "2.2.0"
func UpsertCustomModelsHandler(w http.ResponseWriter, r *http.Request) {
log.Println("Received request for CreateCustomModelHandler")
auth := Authenticate(w, r, true)
if auth == nil {
return
}
if !requireMinClientVersion(w, r, CustomModelsMinClientVersion) {
return
}
var modelsInput shared.ModelsInput
if err := json.NewDecoder(r.Body).Decode(&modelsInput); err != nil {
log.Printf("Error decoding request body: %v\n", err)
http.Error(w, "Invalid request body: "+err.Error(), http.StatusBadRequest)
return
}
if len(modelsInput.CustomProviders) > 0 {
if os.Getenv("IS_CLOUD") != "" {
http.Error(w, "Custom model providers are not supported on Plandex Cloud", http.StatusBadRequest)
return
}
}
if len(modelsInput.CustomModels) > 0 {
if os.Getenv("IS_CLOUD") != "" {
apiOrg, err := getApiOrg(auth.OrgId)
if err != nil {
log.Printf("Error fetching org: %v\n", err)
http.Error(w, "Failed to create custom model: "+err.Error(), http.StatusInternalServerError)
return
}View on GitHub (pinned to e2d772072e)
Solutions
- Read the json error in the message/log (e.g. 'unexpected end of JSON input', 'cannot unmarshal string into Go value of type ...') to pinpoint the malformation
- Send a valid JSON body matching shared.ModelsInput (customModels and customProviders arrays of objects)
- Ensure the client version is >= 2.2.0 (CustomModelsMinClientVersion) and Content-Type is application/json
Example fix
// before
curl -X POST $BASE/custom-models -d 'customModels=my-model'
// after
curl -X POST $BASE/custom-models -H 'Content-Type: application/json' \
-d '{"customModels":[{"provider":"my-provider","model":"my-model"}]}' Defensive patterns
Strategy: validation
Validate before calling
const body = { customModels: [{ provider: 'p', model: 'm' }], customProviders: [] }
const payload = JSON.stringify(body)
JSON.parse(payload) // verify it's valid JSON before sending
if (!Array.isArray(body.customModels)) throw new TypeError('customModels must be an array')
// also ensure client version >= 2.2.0 Type guard
function isModelsInput(v) {
return v != null && typeof v === 'object' &&
Array.isArray(v.customModels) && Array.isArray(v.customProviders)
} Try / catch
try {
await client.upsertCustomModels(body)
} catch (e) {
if (e.status === 400 && String(e.message).includes('Invalid request body')) {
console.error('Payload is not valid JSON for ModelsInput:', e.message)
}
throw e
} Prevention
- Always JSON.stringify the payload and set Content-Type: application/json
- Validate body against the ModelsInput schema before sending
- Ensure client version meets the 2.2.0 minimum for custom models
- Never send an empty body or form-encoded data to this endpoint
When it happens
Trigger: POST to the custom models upsert endpoint with: non-JSON body, truncated JSON, wrong field types (e.g. customModels as a string instead of array), Content-Type/body mismatch, or an empty body.
Common situations: Older CLI (<2.2.0) sending a legacy payload shape; hand-built curl missing quotes or with a stale JSON template; proxy stripping the body; client sending form-encoded data instead of JSON.
Related errors
- Error parsing request body
- Error unmarshalling request:
- Error decoding request body
- Error parsing request body
- Error parsing request body
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/e5c4043168a6463f.
Report an issue: GitHub.