{"record":{"id":"96d9bdbed2324caf","repo":"can1357/oh-my-pi","slug":"pattern-must-not-be-empty","errorCode":null,"errorMessage":"Pattern must not be empty","messagePattern":"Pattern must not be empty","errorType":"validation","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/grep.ts","lineNumber":960,"sourceCode":"\t\tthis.#contextOverride = context !== undefined ? Math.max(0, Math.floor(context)) : undefined;\n\t\tconst total = options?.totalMatchLimit;\n\t\tthis.#totalMatchLimit = total !== undefined ? Math.max(1, Math.floor(total)) : undefined;\n\t}\n\n\tasync execute(\n\t\t_toolCallId: string,\n\t\tparams: SearchParams,\n\t\tsignal?: AbortSignal,\n\t\t_onUpdate?: AgentToolUpdateCallback<GrepToolDetails>,\n\t\t_toolContext?: AgentToolContext,\n\t): Promise<AgentToolResult<GrepToolDetails>> {\n\t\tconst { pattern, path: rawPath, case: caseSensitive, gitignore, skip } = params;\n\n\t\treturn untilAborted(signal, async () => {\n\t\t\t// Preserve the pattern verbatim — leading/trailing whitespace is\n\t\t\t// meaningful in regexes (indentation anchors, trailing-space matches).\n\t\t\tif (!pattern.trim()) {\n\t\t\t\tthrow new ToolError(\"Pattern must not be empty\");\n\t\t\t}\n\t\t\tconst normalizedPattern = pattern;\n\n\t\t\tconst normalizedSkip =\n\t\t\t\tskip === undefined || skip === null ? 0 : Number.isFinite(skip) ? Math.floor(skip) : Number.NaN;\n\t\t\tif (normalizedSkip < 0 || !Number.isFinite(normalizedSkip)) {\n\t\t\t\tthrow new ToolError(\"Skip must be a non-negative number\");\n\t\t\t}\n\t\t\tconst scopedPaths = toPathList(rawPath);\n\t\t\tconst effectivePaths = scopedPaths.length > 0 ? scopedPaths : [\".\"];\n\t\t\tconst rawEntries = await expandDelimitedPathEntries(effectivePaths, this.session.cwd);\n\t\t\tconst pathSpecs = await parsePathSpecs(rawEntries, this.session.cwd);\n\t\t\tconst materializedExternalPaths = new Map<string, string>();\n\t\t\tconst materializeExternalUrlForSearch = async (rawPath: string) => {\n\t\t\t\tconst target = parseReadUrlTarget(rawPath);\n\t\t\t\tif (!target) return undefined;\n\t\t\t\tconst materialized = await materializeReadUrlToFile(\n\t\t\t\t\tthis.session,","sourceCodeStart":942,"sourceCodeEnd":978,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/grep.ts#L942-L978","documentation":"The grep tool requires a non-empty pattern. The check trims the pattern before testing, so a pattern of only whitespace (spaces, tabs, newlines) is also rejected, even though whitespace can be meaningful inside regexes — a genuinely meaningful all-whitespace regex cannot be expressed via this path.","triggerScenarios":"Calling grep with pattern \"\", \"   \", \"\\n\", or pattern consisting solely of whitespace; often the result of an unfilled template variable or a stripped argument.","commonSituations":"A build step or script interpolates an empty environment variable into the pattern; an LLM/agent emits an empty pattern; a CLI flag default of \"\" passed straight through.","solutions":["Supply the intended search text or regex in `pattern`","If you truly meant to match a literal space, use an explicit regex like `^[ \\t]+` or ` +`","Validate that the interpolated variable is non-empty before invoking grep"],"exampleFix":"// before\nconst term = process.env.SEARCH_TERM ?? \"\";\nawait grep({ pattern: term });\n// after\nconst term = process.env.SEARCH_TERM;\nif (!term?.trim()) throw new Error(\"SEARCH_TERM is required\");\nawait grep({ pattern: term });","handlingStrategy":"validation","validationCode":"if (!pattern?.trim()) throw new Error(\"grep pattern must be non-empty\");","typeGuard":"const hasPattern = (p: unknown): p is string => typeof p === \"string\" && p.trim().length > 0;","tryCatchPattern":null,"preventionTips":["Validate interpolated variables before passing as pattern","Express literal-whitespace searches as explicit regexes like ^[ \\t]+"],"tags":["grep","validation","empty-argument"],"backgroundTag":"empty-required-argument","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}