can1357/oh-my-pi · error · ToolError
Pattern must not be empty
Error message
Pattern must not be empty
What it means
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.
Source
Thrown at packages/coding-agent/src/tools/grep.ts:960
this.#contextOverride = context !== undefined ? Math.max(0, Math.floor(context)) : undefined;
const total = options?.totalMatchLimit;
this.#totalMatchLimit = total !== undefined ? Math.max(1, Math.floor(total)) : undefined;
}
async execute(
_toolCallId: string,
params: SearchParams,
signal?: AbortSignal,
_onUpdate?: AgentToolUpdateCallback<GrepToolDetails>,
_toolContext?: AgentToolContext,
): Promise<AgentToolResult<GrepToolDetails>> {
const { pattern, path: rawPath, case: caseSensitive, gitignore, skip } = params;
return untilAborted(signal, async () => {
// Preserve the pattern verbatim — leading/trailing whitespace is
// meaningful in regexes (indentation anchors, trailing-space matches).
if (!pattern.trim()) {
throw new ToolError("Pattern must not be empty");
}
const normalizedPattern = pattern;
const normalizedSkip =
skip === undefined || skip === null ? 0 : Number.isFinite(skip) ? Math.floor(skip) : Number.NaN;
if (normalizedSkip < 0 || !Number.isFinite(normalizedSkip)) {
throw new ToolError("Skip must be a non-negative number");
}
const scopedPaths = toPathList(rawPath);
const effectivePaths = scopedPaths.length > 0 ? scopedPaths : ["."];
const rawEntries = await expandDelimitedPathEntries(effectivePaths, this.session.cwd);
const pathSpecs = await parsePathSpecs(rawEntries, this.session.cwd);
const materializedExternalPaths = new Map<string, string>();
const materializeExternalUrlForSearch = async (rawPath: string) => {
const target = parseReadUrlTarget(rawPath);
if (!target) return undefined;
const materialized = await materializeReadUrlToFile(
this.session,View on GitHub (pinned to 9690622007)
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
Example fix
// before
const term = process.env.SEARCH_TERM ?? "";
await grep({ pattern: term });
// after
const term = process.env.SEARCH_TERM;
if (!term?.trim()) throw new Error("SEARCH_TERM is required");
await grep({ pattern: term }); Defensive patterns
Strategy: validation
Validate before calling
if (!pattern?.trim()) throw new Error("grep pattern must be non-empty"); Type guard
const hasPattern = (p: unknown): p is string => typeof p === "string" && p.trim().length > 0;
Prevention
- Validate interpolated variables before passing as pattern
- Express literal-whitespace searches as explicit regexes like ^[ \t]+
When it happens
Trigger: Calling grep with pattern "", " ", "\n", or pattern consisting solely of whitespace; often the result of an unfilled template variable or a stripped argument.
Common situations: 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.
Related errors
- Skip must be a non-negative number
- Invalid regex: ${err.message}
- Unsupported language '{value}'. Supported: {}
- Unable to infer language from file extension: {}. Specify `l
- Invalid pattern: {err}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/96d9bdbed2324caf.
Report an issue: GitHub.