{"record":{"id":"3c05ffb911481b7f","repo":"CherryHQ/cherry-studio","slug":"pattern-is-required-for-grep","errorCode":null,"errorMessage":"Pattern is required for grep","messagePattern":"Pattern is required for grep","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"src/main/ai/mcp/servers/filesystem/tools/grep.ts","lineNumber":45,"sourceCode":"- Results are limited to 100 matches\n- Binary files are automatically skipped\n- Common directories (node_modules, .git, dist) are excluded\n- The path parameter must resolve within the configured workspace root if specified\n- If path is not specified, defaults to the base directory`,\n  inputSchema: z.toJSONSchema(GrepToolSchema)\n}\n\n// Handler implementation\nexport async function handleGrepTool(args: unknown, baseDir: string) {\n  const parsed = GrepToolSchema.safeParse(args)\n  if (!parsed.success) {\n    throw new Error(`Invalid arguments for grep: ${parsed.error}`)\n  }\n\n  const data = parsed.data\n\n  if (!data.pattern) {\n    throw new Error('Pattern is required for grep')\n  }\n\n  const searchPath = data.path || baseDir\n  const validPath = await validatePath(searchPath, baseDir)\n\n  const matches: GrepMatch[] = []\n  let truncated = false\n  let regex: RegExp\n\n  // Build ripgrep arguments\n  const rgArgs: string[] = [\n    '--no-heading',\n    '--line-number',\n    '--color',\n    'never',\n    '--ignore-case',\n    '--glob',\n    '!.git/**',","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/src/main/ai/mcp/servers/filesystem/tools/grep.ts#L27-L63","documentation":"After zod parsing succeeds, the handler does an explicit truthiness check on data.pattern — an empty string ('') passes z.string() but is not a usable regex. This guard fires before the regex is constructed, so the caller gets a clear message instead of a confusing 'Invalid regex pattern' for the empty string. It is belt-and-suspenders with the later regex try/catch (error 317).","triggerScenarios":"The caller sends pattern as ''. zod accepts ''; this guard rejects it. Distinct from a malformed regex (which would hit error 317).","commonSituations":"A model sending an empty pattern expecting 'match everything'; a templating layer that substitutes undefined with ''; a client bug that drops the pattern field value while keeping the key.","solutions":["Provide a concrete regex pattern. To match everything, use '.*'.","If the intent is 'list files' rather than 'search contents', use the glob tool instead of grep."],"exampleFix":"// before\nif (!data.pattern) {\n  throw new Error('Pattern is required for grep')\n}\n\n// after — collapse this guard into the zod schema so there is one validation site\n// (in the schema): pattern: z.string().min(1).describe('...')\n// then remove the redundant runtime check","handlingStrategy":"validation","validationCode":"// Reject empty grep patterns before dispatching.\nfunction isNonEmptyGrepPattern(p: unknown): boolean {\n  return typeof p === 'string' && p.length > 0\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Send a concrete regex; use '.*' to match anything rather than ''.","Use the glob tool if the intent is to list files rather than search contents.","Move the empty check into the zod schema (z.string().min(1)) to consolidate validation.","Distinguish 'empty pattern' from 'no matches' in error handling."],"tags":["filesystem","grep","validation","mcp-tool"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}