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.ServerAuth

View on GitHub (pinned to e2d772072e)

Solutions

  1. Use a model that reliably emits strict JSON for tool responses
  2. Increase max_tokens to avoid truncated JSON and retry
  3. Strip code fences/whitespace before parsing (server-side patch) or prefer the XML/tool path
  4. 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

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


AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05). Data as JSON: /api/errors/d307c1efbe810fc7. Report an issue: GitHub.