CherryHQ/cherry-studio · warning · Error

Invalid thoughtNumber: must be a number

Error message

Invalid thoughtNumber: must be a number

What it means

The sequential-thinking server validates `thoughtNumber` as a number with `!data.thoughtNumber || typeof !== 'number'`. Note the `!data.thoughtNumber` clause ALSO rejects `0` (falsy), so valid values must be >= 1. It throws a plain `Error`, caught and returned as an `isError: true` tool result (not a thrown exception).

Source

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

  revisesThought?: number
  branchFromThought?: number
  branchId?: string
  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. Use a 1-based integer: `{ thoughtNumber: 1 }`.
  2. Coerce with `Number(...)` and ensure `>= 1` before calling.
  3. On revisions/branches, still pass a valid monotonic `thoughtNumber`.

Example fix

// before
{ thoughtNumber: 0, ... }
// after
{ thoughtNumber: 1, ... }
Defensive patterns

Strategy: type-guard

Validate before calling

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

Type guard

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

Try / catch

const result = await client.callTool({ name: 'sequentialthinking', arguments: { ...raw, thoughtNumber: normalizeThoughtNumber(raw.thoughtNumber) } })
if (result.isError) {
  const body = JSON.parse((result.content[0] as any).text)
  if (/thoughtNumber/.test(body.error)) {/* use 1-based numbering and retry */}
}

Prevention

When it happens

Trigger: Submitting `thoughtNumber` missing, null, a string like `"1"`, or `0`. The advertised inputSchema enforces `minimum: 1`, matching the runtime `0` rejection.

Common situations: The model zero-indexes its thoughts; passes a stringified number; omits the field on a revision/branch call.

Related errors


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