CherryHQ/cherry-studio · warning · Error

Invalid totalThoughts: must be a number

Error message

Invalid totalThoughts: must be a number

What it means

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.

Source

Thrown at src/main/ai/mcp/servers/sequentialthinking.ts:39

  needsMoreThoughts?: boolean
  nextThoughtNeeded: boolean
}

class SequentialThinkingServer {
  private thoughtHistory: ThoughtData[] = []
  private branches: Record<string, ThoughtData[]> = {}

  private validateThoughtData(input: unknown): ThoughtData {
    const data = input as Record<string, unknown>

    if (!data.thought || typeof data.thought !== 'string') {
      throw new Error('Invalid thought: must be a string')
    }
    if (!data.thoughtNumber || typeof data.thoughtNumber !== 'number') {
      throw new Error('Invalid thoughtNumber: must be a number')
    }
    if (!data.totalThoughts || typeof data.totalThoughts !== 'number') {
      throw new Error('Invalid totalThoughts: must be a number')
    }
    if (typeof data.nextThoughtNeeded !== 'boolean') {
      throw new Error('Invalid nextThoughtNeeded: must be a boolean')
    }

    return {
      thought: data.thought,
      thoughtNumber: data.thoughtNumber,
      totalThoughts: data.totalThoughts,
      nextThoughtNeeded: data.nextThoughtNeeded,
      isRevision: data.isRevision as boolean | undefined,
      revisesThought: data.revisesThought as number | undefined,
      branchFromThought: data.branchFromThought as number | undefined,
      branchId: data.branchId as string | undefined,
      needsMoreThoughts: data.needsMoreThoughts as boolean | undefined
    }
  }

View on GitHub (pinned to 726446b54c)

Solutions

  1. Pass a positive integer estimate: `{ totalThoughts: 5 }` (adjustable later).
  2. Coerce and bound-check `>= 1` before dispatch.
  3. If unsure of the total, overestimate — the server allows `thoughtNumber > totalThoughts` and self-corrects.

Example fix

// before
{ totalThoughts: "5", ... }
// after
{ totalThoughts: 5, ... }
Defensive patterns

Strategy: type-guard

Validate before calling

function normalizeTotalThoughts(v: unknown): number {
  const n = typeof v === 'string' ? Number(v) : v
  if (typeof n !== 'number' || !Number.isFinite(n) || n < 1) {
    throw new TypeError("'totalThoughts' must be a number >= 1")
  }
  return Math.floor(n)
}

Type guard

const isValidTotalThoughts = (v: unknown): v is number =>
  typeof v === 'number' && Number.isFinite(v) && v >= 1

Try / catch

const result = await client.callTool({ name: 'sequentialthinking', arguments: { ...raw, totalThoughts: normalizeTotalThoughts(raw.totalThoughts) } })
if (result.isError) {
  const body = JSON.parse((result.content[0] as any).text)
  if (/totalThoughts/.test(body.error)) {/* pass a positive integer estimate */}
}

Prevention

When it happens

Trigger: 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.

Common situations: The model passes a string estimate; omits the field; uses `0` to mean 'unknown'.

Related errors


AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12). Data as JSON: /api/errors/10f23985ff1f6f8c. Report an issue: GitHub.