{"record":{"id":"da19605cb14b8a8e","repo":"can1357/oh-my-pi","slug":"pat-must-be-a-non-empty-pattern","errorCode":null,"errorMessage":"`pat` must be a non-empty pattern","messagePattern":"`pat` must be a non-empty pattern","errorType":"validation","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/ast-grep.ts","lineNumber":201,"sourceCode":"\t\t\tcaption: \"Loosest existence check for a symbol in one file\",\n\t\t\tcall: { pat: \"processItems\", path: \"src/worker.ts\" },\n\t\t},\n\t];\n\treadonly loadMode = \"discoverable\";\n\n\tconstructor(private readonly session: ToolSession) {}\n\n\tasync execute(\n\t\t_toolCallId: string,\n\t\tparams: typeof astGrepSchema.infer,\n\t\tsignal?: AbortSignal,\n\t\t_onUpdate?: AgentToolUpdateCallback<AstGrepToolDetails>,\n\t\t_context?: AgentToolContext,\n\t): Promise<AgentToolResult<AstGrepToolDetails>> {\n\t\treturn untilAborted(signal, async () => {\n\t\t\tconst pattern = params.pat.trim();\n\t\t\tif (pattern.length === 0) {\n\t\t\t\tthrow new ToolError(\"`pat` must be a non-empty pattern\");\n\t\t\t}\n\t\t\tconst patterns = [pattern];\n\t\t\tconst skip = params.skip === undefined ? 0 : Math.floor(params.skip);\n\t\t\tif (!Number.isFinite(skip) || skip < 0) {\n\t\t\t\tthrow new ToolError(\"skip must be a non-negative number\");\n\t\t\t}\n\t\t\tconst scopedPaths = toPathList(params.path);\n\t\t\tconst rawPaths = scopedPaths.length > 0 ? scopedPaths : [\".\"];\n\t\t\tconst scope = await resolveToolSearchScope({\n\t\t\t\trawPaths,\n\t\t\t\tcwd: this.session.cwd,\n\t\t\t\tinternalUrlAction: \"search\",\n\t\t\t\tsettings: this.session.settings,\n\t\t\t\tsignal,\n\t\t\t\tsessionFile: this.session.getSessionFile() ?? undefined,\n\t\t\t\tlocalProtocolOptions: this.session.localProtocolOptions,\n\t\t\t\tskills: this.session.skills,\n\t\t\t\tresolveExternalUrl: async rawPath => {","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/ast-grep.ts#L183-L219","documentation":"The ast-grep tool requires a search pattern. The tool trims `params.pat` and throws this ToolError when the result is empty, because running ast-grep with no pattern is meaningless. It guards against the agent or caller passing whitespace-only or missing patterns.","triggerScenarios":"Calling AstGrepTool.execute with params.pat undefined, an empty string (\"\"), or a string of only whitespace (e.g. \"   \").","commonSituations":"An LLM agent emits an empty `pat` argument when the pattern is optional in its schema; a pipeline passes a user-supplied pattern after trimming it to nothing; a template fills `pat` from a variable that was never set.","solutions":["Supply a non-empty ast-grep pattern in `pat` (e.g. \"$A === $B\").","Trim/validate the pattern client-side before invoking the tool and skip the call if empty.","Ensure the tool schema marks `pat` as required so the model cannot omit it."],"exampleFix":"// before\nawait tool.execute({ pat: \"\" }, ctx);\n\n// after\nconst pat = \"console.log($MSG)\";\nif (pat.trim()) await tool.execute({ pat }, ctx);","handlingStrategy":"validation","validationCode":"const pat = (params.pat ?? \"\").trim();\nif (pat.length === 0) throw new Error(\"ast-grep pattern required before calling tool\");\nawait tool.execute({ ...params, pat }, ctx);","typeGuard":null,"tryCatchPattern":"try {\n  await tool.execute({ pat }, ctx);\n} catch (e) {\n  if (e instanceof ToolError && e.message.includes(\"non-empty pattern\")) {\n    // surface a fix-hint to the caller / re-prompt with a pattern\n  } else throw e;\n}","preventionTips":["Make `pat` a required field in the tool schema exposed to the model.","Trim and check patterns before every ast-grep call.","Log empty-pattern attempts to spot prompt/schema gaps."],"tags":["validation","tool-input","ast-grep"],"backgroundTag":"empty-required-parameter","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}