sinelaw/fresh · error

grep exited with code

Error message

grep exited with code ${r.exit_code}: ${r.stderr}

What it means

The live_grep plugin's plain `grep` provider throws this when GNU/BSD grep exits with a code other than 0 (matches) or 1 (no matches — parsed as an empty result). Any other code (commonly 2) means grep failed: an invalid pattern, unreadable files, or bad flags. grep's stderr is included in the message.

Solutions

  1. Fix the query pattern if regex mode is on (use POSIX-compatible syntax).
  2. Install ripgrep so the higher-priority rg provider is used instead of the grep fallback.
  3. Run `grep -rn <pattern> .` manually in the cwd and read stderr to identify flag/pattern issues.
  4. Check which grep is in PATH (GNU vs BSD) and align flag expectations.
Defensive patterns

Strategy: fallback

Validate before calling

if (regexMode) { try { new RegExp(query); } catch { throw new Error(`invalid regex: ${query}`); } }
try { await editor.spawnProcess("grep", ["--version"], cwd); } catch { /* no grep either */ }

Type guard

function isGrepExitOk(r) { return r.exit_code === 0 || r.exit_code === 1; }

Try / catch

try {
  results = await grepProvider.search(query, opts);
} catch (e) {
  if (/grep exited with code 2/.test(String(e))) {
    results = await grepProvider.search(query, { ...opts, regex: false });
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling live-grep with the grep (fallback) provider when: (1) the query is an invalid BRE/ERE pattern (grep exit 2), (2) flags built by the plugin are unsupported by the installed grep flavor (e.g. BSD vs GNU differences for -P/--include style options), or (3) the cwd cannot be read.

Common situations: Systems without ripgrep where the grep fallback runs and the user's regex uses PCRE syntax GNU grep -P would reject or BSD grep doesn't support; macOS BSD grep choking on GNU-only flags; malformed patterns like '[' in regex mode.

Understand the failure class

Background: "git command failed": what it means when a tool shells out to git and git exits non-zero — this error's family across 21 libraries.

Related errors


AI-assisted analysis of sinelaw/fresh@67894ca546 (2026-09-13). Data as JSON: /api/errors/818ab24ddd0e9156. Report an issue: GitHub.

Appendix: source

Thrown at crates/fresh-editor/plugins/live_grep.ts:639

  },
  search: async (query, { cwd, maxResults, wholeWord, regex }) => {
    const args = [
      "-rn",
      "-I",
      "--exclude-dir=.git",
      "--exclude-dir=node_modules",
      "--exclude-dir=target",
    ];
    args.push(regex === false ? "-F" : "-E");
    if (wholeWord) args.push("-w");
    args.push("--", query, ".");
    const r = await editor.spawnProcess("grep", args, cwd);
    if (r.exit_code === 0 || r.exit_code === 1) {
      // grep emits `path:line:content` (no column). parseGrepOutput's
      // 3-field fallback handles the missing column (defaults to 1).
      return parseGrepOutput(r.stdout, maxResults, (msg) => editor.debug(msg)) as GrepMatch[];
    }
    throw new Error(`grep exited with code ${r.exit_code}: ${r.stderr}`);
  },
});

// ── Wiring ──────────────────────────────────────────────────────

function badgeFor(source: ScopeId | undefined): string {
  if (!source || source === "files") return "";
  const def = SCOPES.find((s) => s.id === source);
  return def?.badge ? `[${def.badge}] ` : "";
}

const finder = new Finder<GrepMatch>(editor, {
  id: "live-grep",
  format: (match) => ({
    label: `${badgeFor(match.source)}${match.file}:${match.line}`,
    description:
      match.content.length > 60
        ? match.content.substring(0, 57).trim() + "..."

View on GitHub (pinned to 67894ca546)