sinelaw/fresh · error

rg exited with code

Error message

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

What it means

The live_grep plugin's `rg` provider shells out to ripgrep via editor.spawnProcess and throws this error whenever rg terminates with a status other than 0. Unlike the ag/git-grep/ack providers, this one only treats exit code 0 as success, so even ripgrep's benign 'no matches found' exit code 1 becomes an error. Non-zero codes also cover real failures such as exit 2 for an invalid regex pattern or unreadable files, with details in stderr.

Solutions

  1. If regex mode is on, fix the query pattern (escape special characters or use literal mode).
  2. If the query is simply a no-match, note this provider throws on exit 1 — fix the provider to accept `r.exit_code === 0 || r.exit_code === 1` like the ag/git-grep providers do.
  3. Run `rg <pattern>` manually in the target cwd and read stderr to see the exact ripgrep failure.
  4. Verify ripgrep is installed and up to date (`rg --version`).

Example fix

// before
if (r.exit_code === 0) {
  return parseGrepOutput(r.stdout, maxResults, (msg) => editor.debug(msg)) as GrepMatch[];
}
// after
if (r.exit_code === 0 || r.exit_code === 1) {
  // rg exits 1 when there are no matches — treat as empty.
  return parseGrepOutput(r.stdout, maxResults, (msg) => editor.debug(msg)) as GrepMatch[];
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (regexMode) { try { new RegExp(query); } catch { throw new Error(`invalid regex: ${query}`); } }
if (typeof editor.spawnProcess !== "function") throw new Error("spawnProcess unavailable");

Type guard

function isGrepResult(r) { return typeof r === "object" && r !== null && typeof r.exit_code === "number" && typeof r.stdout === "string" && typeof r.stderr === "string"; }

Try / catch

try {
  const matches = await rgProvider.search(query, opts);
} catch (e) {
  if (/rg exited with code 2/.test(String(e))) {
    // invalid pattern — retry with literal mode
    matches = await rgProvider.search(query, { ...opts, regex: false });
  } else if (/rg exited with code 1/.test(String(e))) {
    matches = []; // no matches surfaced as an error by this provider
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Calling the live-grep search with the rg provider active when: (1) rg finds no matches (exit 1, not whitelisted here), (2) the query is an invalid regex while regex mode is on (rg exit 2), (3) rg is missing/broken enough to fail, or (4) the cwd is unreadable.

Common situations: Typing a regex query like '[' or 'a(' with regex mode enabled; searching a term that genuinely has no matches (because exit 1 is not handled as empty like the other providers); running in a directory rg cannot traverse; an rg version with different flag support causing argument errors.

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/fa3d3330428fca48. Report an issue: GitHub.

Appendix: source

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

      "-g", "!.git",
    ];
    if (regex === false) args.push("--fixed-strings");
    if (wholeWord) args.push("--word-regexp");
    if (includeIgnored) {
      // Search ignored *and* hidden files (dotfiles). `.git` stays
      // excluded via the glob above.
      args.push("--no-ignore", "--hidden");
    } else {
      // Default: respect ignore files, plus prune the usual heavy
      // build/vendor dirs and lockfiles that bury real hits.
      args.push("-g", "!node_modules", "-g", "!target", "-g", "!*.lock");
    }
    args.push("--", query);
    const r = await editor.spawnProcess("rg", args, cwd);
    if (r.exit_code === 0) {
      return parseGrepOutput(r.stdout, maxResults, (msg) => editor.debug(msg)) as GrepMatch[];
    }
    throw new Error(`rg exited with code ${r.exit_code}: ${r.stderr}`);
  },
});

registerProvider({
  name: "ag",
  priority: -2,
  isAvailable: async () => {
    try {
      const r = await editor.spawnProcess("ag", ["--version"], editor.getCwd());
      return r.exit_code === 0;
    } catch {
      return false;
    }
  },
  search: async (query, { cwd, maxResults, wholeWord, regex }) => {
    const args = [
      "--column",
      "--numbers",

View on GitHub (pinned to 67894ca546)