plandex-ai/plandex · error
error unmarshalling plan description response: %v
Error message
error unmarshalling plan description response: %v
What it means
After receiving the model's content in the non-XML path, genPlanDescription expects it to be JSON matching shared.ConvoMessageDescription and unmarshals it. If the content is not valid JSON (or has the wrong shape), json.Unmarshal fails and the server returns this 500 ApiError.
Source
Thrown at app/server/model/plan/commit_msg.go:159
if content == "" {
fmt.Println("no describePlan function call found in response")
go notify.NotifyErr(notify.SeverityError, fmt.Errorf("no describePlan function call found in response"))
return nil, &shared.ApiError{
Type: shared.ApiErrorTypeOther,
Status: http.StatusInternalServerError,
Msg: "No describePlan function call found in response. The model failed to generate a valid response.",
}
}
var desc shared.ConvoMessageDescription
err = json.Unmarshal([]byte(content), &desc)
if err != nil {
fmt.Printf("Error unmarshalling plan description response: %v\n", err)
go notify.NotifyErr(notify.SeverityError, fmt.Errorf("error unmarshalling plan description response: %v", err))
return nil, &shared.ApiError{
Type: shared.ApiErrorTypeOther,
Status: http.StatusInternalServerError,
Msg: fmt.Sprintf("error unmarshalling plan description response: %v", err),
}
}
commitMsg = desc.CommitMsg
}
return &db.ConvoMessageDescription{
PlanId: planId,
CommitMsg: commitMsg,
}, nil
}
type GenCommitMsgForPendingResultsParams struct {
Auth *types.ServerAuthView on GitHub (pinned to e2d772072e)
Solutions
- Use a model that reliably emits strict JSON for tool responses
- Increase max_tokens to avoid truncated JSON and retry
- Strip code fences/whitespace before parsing (server-side patch) or prefer the XML/tool path
- Retry the request — malformed output is often intermittent
Example fix
// before: trusting raw content var desc shared.ConvoMessageDescription err = json.Unmarshal([]byte(content), &desc) // after: strip common wrappers first trimmed := strings.TrimSpace(strings.Trim(content, "` \n")) trimmed = strings.TrimPrefix(strings.TrimPrefix(trimmed, "json"), "\n") err = json.Unmarshal([]byte(trimmed), &desc)
Defensive patterns
Strategy: validation
Validate before calling
// validate JSON shape before unmarshalling into the struct
trimmed := strings.TrimSpace(content)
if !strings.HasPrefix(trimmed, "{") || !json.Valid([]byte(trimmed)) {
return fmt.Errorf("model content is not valid JSON")
} Try / catch
desc, apiErr := genPlanDescription(...)
if apiErr != nil && strings.Contains(apiErr.Msg, "unmarshalling plan description") {
// retry once; intermittent malformed output
return genPlanDescription(...)
} Prevention
- Prefer tool-call/function output over asking the model for free-form JSON
- Increase max_tokens to avoid mid-JSON truncation
- Strip code fences before parsing when using proxies or local models
- Retry once on unmarshal failure — malformed output is often intermittent
When it happens
Trigger: The model returned prose or malformed JSON instead of the expected structured description; a proxy concatenated extra text around the JSON; the response was truncated mid-JSON by max_tokens; a provider returned an error page/body captured as content.
Common situations: Local/partially-tuned models producing trailing commas or comments; responses wrapped in Markdown code fences (```json ... ```) that break strict unmarshalling; long conversations hitting token limits and truncating the JSON.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- no commitMsg tag found in XML response
- client not found for provider composite: %s
- error creating chat completion stream: %w
- stream timed out due to inactivity. The model is not respond
- model stream ended unexpectedly: %w
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/d307c1efbe810fc7.
Report an issue: GitHub.