From dbc1d29d4d0586eda7163ab92d58243dd3f79351 Mon Sep 17 00:00:00 2001 From: Roo Code Date: Sat, 7 Mar 2026 07:53:13 +0000 Subject: [PATCH] fix: guard countMarkdownHeadings against non-string input When a subtask returns to the main task, message.text can be a non-string truthy value (e.g. array or object). The existing falsy check (!text) lets these through, causing a TypeError on .replace(). Add a typeof check so non-string values safely return 0. Fixes #11881 --- webview-ui/src/utils/__tests__/markdown.spec.ts | 8 ++++++++ webview-ui/src/utils/markdown.ts | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/webview-ui/src/utils/__tests__/markdown.spec.ts b/webview-ui/src/utils/__tests__/markdown.spec.ts index 97b3fdaaf2f..542505a009f 100644 --- a/webview-ui/src/utils/__tests__/markdown.spec.ts +++ b/webview-ui/src/utils/__tests__/markdown.spec.ts @@ -8,6 +8,14 @@ describe("markdown heading helpers", () => { expect(countMarkdownHeadings("")).toBe(0) }) + it("returns 0 for non-string truthy values", () => { + // When subtasks return to main task, message.text can be a non-string value + expect(countMarkdownHeadings(["# heading"] as unknown as string)).toBe(0) + expect(countMarkdownHeadings({ text: "# heading" } as unknown as string)).toBe(0) + expect(countMarkdownHeadings(42 as unknown as string)).toBe(0) + expect(countMarkdownHeadings(true as unknown as string)).toBe(0) + }) + it("counts single and multiple headings", () => { expect(countMarkdownHeadings("# One")).toBe(1) expect(countMarkdownHeadings("# One\nContent")).toBe(1) diff --git a/webview-ui/src/utils/markdown.ts b/webview-ui/src/utils/markdown.ts index 7a77b9866db..107a248b22a 100644 --- a/webview-ui/src/utils/markdown.ts +++ b/webview-ui/src/utils/markdown.ts @@ -4,7 +4,7 @@ * Code fences are stripped before matching to avoid false positives. */ export function countMarkdownHeadings(text: string | undefined): number { - if (!text) return 0 + if (!text || typeof text !== "string") return 0 // Remove fenced code blocks to avoid counting headings inside code const withoutCodeBlocks = text.replace(/```[\s\S]*?```/g, "")