{"record":{"id":"10f23985ff1f6f8c","repo":"CherryHQ/cherry-studio","slug":"invalid-totalthoughts-must-be-a-number","errorCode":null,"errorMessage":"Invalid totalThoughts: must be a number","messagePattern":"Invalid totalThoughts: must be a number","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"src/main/ai/mcp/servers/sequentialthinking.ts","lineNumber":39,"sourceCode":"  needsMoreThoughts?: boolean\n  nextThoughtNeeded: boolean\n}\n\nclass SequentialThinkingServer {\n  private thoughtHistory: ThoughtData[] = []\n  private branches: Record<string, ThoughtData[]> = {}\n\n  private validateThoughtData(input: unknown): ThoughtData {\n    const data = input as Record<string, unknown>\n\n    if (!data.thought || typeof data.thought !== 'string') {\n      throw new Error('Invalid thought: must be a string')\n    }\n    if (!data.thoughtNumber || typeof data.thoughtNumber !== 'number') {\n      throw new Error('Invalid thoughtNumber: must be a number')\n    }\n    if (!data.totalThoughts || typeof data.totalThoughts !== 'number') {\n      throw new Error('Invalid totalThoughts: must be a number')\n    }\n    if (typeof data.nextThoughtNeeded !== 'boolean') {\n      throw new Error('Invalid nextThoughtNeeded: must be a boolean')\n    }\n\n    return {\n      thought: data.thought,\n      thoughtNumber: data.thoughtNumber,\n      totalThoughts: data.totalThoughts,\n      nextThoughtNeeded: data.nextThoughtNeeded,\n      isRevision: data.isRevision as boolean | undefined,\n      revisesThought: data.revisesThought as number | undefined,\n      branchFromThought: data.branchFromThought as number | undefined,\n      branchId: data.branchId as string | undefined,\n      needsMoreThoughts: data.needsMoreThoughts as boolean | undefined\n    }\n  }\n","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/src/main/ai/mcp/servers/sequentialthinking.ts#L21-L57","documentation":"The sequential-thinking server validates `totalThoughts` as a number with `!data.totalThoughts || typeof !== 'number'`. As with `thoughtNumber`, the `!data.totalThoughts` clause rejects `0`; valid values are >= 1. It throws a plain `Error`, returned as an `isError: true` tool result, not thrown to the caller. Note `totalThoughts` can be adjusted upward later — but it must always be a positive integer at submit time.","triggerScenarios":"Submitting `totalThoughts` missing, null, a string, or `0`. Even though the server later raises `totalThoughts` to `thoughtNumber` if exceeded, both must be valid positive numbers at entry.","commonSituations":"The model passes a string estimate; omits the field; uses `0` to mean 'unknown'.","solutions":["Pass a positive integer estimate: `{ totalThoughts: 5 }` (adjustable later).","Coerce and bound-check `>= 1` before dispatch.","If unsure of the total, overestimate — the server allows `thoughtNumber > totalThoughts` and self-corrects."],"exampleFix":"// before\n{ totalThoughts: \"5\", ... }\n// after\n{ totalThoughts: 5, ... }","handlingStrategy":"type-guard","validationCode":"function normalizeTotalThoughts(v: unknown): number {\n  const n = typeof v === 'string' ? Number(v) : v\n  if (typeof n !== 'number' || !Number.isFinite(n) || n < 1) {\n    throw new TypeError(\"'totalThoughts' must be a number >= 1\")\n  }\n  return Math.floor(n)\n}","typeGuard":"const isValidTotalThoughts = (v: unknown): v is number =>\n  typeof v === 'number' && Number.isFinite(v) && v >= 1","tryCatchPattern":"const result = await client.callTool({ name: 'sequentialthinking', arguments: { ...raw, totalThoughts: normalizeTotalThoughts(raw.totalThoughts) } })\nif (result.isError) {\n  const body = JSON.parse((result.content[0] as any).text)\n  if (/totalThoughts/.test(body.error)) {/* pass a positive integer estimate */}\n}","preventionTips":["Pass a positive integer estimate; overestimate if unsure — the server self-corrects upward.","Coerce and bound-check before sending.","Never use 0 to mean 'unknown'."],"tags":["mcp","validation","sequential-thinking","soft-error"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}