CherryHQ/cherry-studio · warning · Error

Invalid arguments for ls: ${parsed.error}

Error message

Invalid arguments for ls: ${parsed.error}

What it means

Zod safeParse on the ls tool's arguments failed. LsToolSchema accepts an optional string `path` and an optional boolean `recursive`; both are optional, so this fires only on type errors — a non-string path or a non-boolean recursive. parsed.error identifies the offending field. Returned as an isError tool result.

Source

Thrown at src/main/ai/mcp/servers/filesystem/tools/ls.ts:34

  description: `Lists files and directories in a specified path.

- Returns a tree-like structure with icons (📁 directories, 📄 files)
- Shows the absolute directory path in the header
- Entries are sorted alphabetically with directories first
- Can list recursively with recursive=true (up to 5 levels deep)
- Common directories (node_modules, dist, .git) are excluded
- Hidden files (starting with .) are excluded except .env.example
- Results are limited to 100 entries
- The path parameter must resolve within the configured workspace root if specified
- If path is not specified, defaults to the base directory`,
  inputSchema: z.toJSONSchema(LsToolSchema)
}

// Handler implementation
export async function handleLsTool(args: unknown, baseDir: string) {
  const parsed = LsToolSchema.safeParse(args)
  if (!parsed.success) {
    throw new Error(`Invalid arguments for ls: ${parsed.error}`)
  }

  const targetPath = parsed.data.path || baseDir
  const validPath = await validatePath(targetPath, baseDir)
  const recursive = parsed.data.recursive || false

  interface TreeNode {
    name: string
    type: 'file' | 'directory'
    children?: TreeNode[]
  }

  let fileCount = 0
  let truncated = false

  async function buildTree(dirPath: string, depth: number = 0): Promise<TreeNode[]> {
    if (fileCount >= MAX_FILES_LIMIT) {
      truncated = true

View on GitHub (pinned to 726446b54c)

Solutions

  1. Send path as an absolute string (or omit it) and recursive as a boolean (or omit it).
  2. Read parsed.error to find which field has the wrong type.
  3. Ensure the client does not stringify booleans when serializing the arguments object.

Example fix

// before
throw new Error(`Invalid arguments for ls: ${parsed.error}`)

// after — structured issues
if (!parsed.success) {
  const issues = parsed.error.issues.map(i => `${i.path.join('.') || '(root)'}: ${i.message}`).join('; ')
  throw new Error(`Invalid arguments for ls: ${issues}`)
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate ls args on the client (both fields optional).
function isValidLsArgs(a: unknown): a is { path?: string; recursive?: boolean } {
  if (typeof a !== 'object' || a === null) return true // both optional
  const o = a as any
  return (o.path === undefined || typeof o.path === 'string')
    && (o.recursive === undefined || typeof o.recursive === 'boolean')
}

Type guard

function isLsArgs(a: unknown): a is { path?: string; recursive?: boolean } {
  if (typeof a !== 'object' || a === null) return true
  const o = a as any
  return (o.path === undefined || typeof o.path === 'string')
    && (o.recursive === undefined || typeof o.recursive === 'boolean')
}

Prevention

When it happens

Trigger: The caller sends path as a number/object/null or recursive as a non-boolean (e.g. the string 'true'). Because both fields are optional, omitting them entirely does not trigger this error.

Common situations: A client serializing recursive:true as the string 'true'; a model passing a number where a path is expected; schema drift where the client thinks path is required and sends path:null.

Related errors


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