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

  1. Supply the intended search text or regex in `pattern`
  2. If you truly meant to match a literal space, use an explicit regex like `^[ \t]+` or ` +`
  3. 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

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


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/96d9bdbed2324caf. Report an issue: GitHub.