Mintplex-Labs/anything-llm · error · Error
${result.stderr || `ripgrep exited with code ${result.status
Error message
${result.stderr || `ripgrep exited with code ${result.status}`} What it means
Thrown by listFilesWithRipgrep after spawnSync runs the bundled ripgrep binary in --files mode. Ripgrep exit code 0 means success, 1 means no matches (not an error), and anything >1 is a real failure (bad flag, permission denied, unreadable path, binary crash, or maxBuffer exceeded). The error surfaces whatever ripgrep wrote to stderr, or a generic exit-code message if stderr is empty.
Source
Thrown at server/utils/agents/aibitat/plugins/filesystem/search-files.js:292
const args = [
"--files", // List files instead of searching content
"--no-ignore", // Search all files, even those in .gitignore
];
// Add glob patterns (ripgrep uses --glob for filtering --files output)
for (const pattern of patterns) args.push("--glob", pattern);
for (const exclude of excludePatterns) args.push("--glob", `!${exclude}`);
// The "--" prevents searchPath from being parsed as an option if it starts with "-"
// (defense against argument injection attacks)
args.push("--", searchPath);
const result = spawnSync(rgPath, args, {
encoding: "utf-8",
maxBuffer: 10 * 1024 * 1024,
});
if (result.status > 1) {
throw new Error(
result.stderr || `ripgrep exited with code ${result.status}`
);
}
// unique files
const files = new Set();
if (!result.stdout) return { files: Array.from(files), method: "ripgrep" };
const lines = result.stdout.trim().split("\n").filter(Boolean);
for (const line of lines) {
files.add(line);
if (files.size >= maxResults) break;
}
return { files: Array.from(files), method: "ripgrep" };
}
/**View on GitHub (pinned to 526360e320)
Solutions
- Check the stderr fragment in the error message — ripgrep usually states the exact problem (e.g. 'permission denied', 'regex error').
- Verify the searchPath exists and is readable by the AnythingLLM process user (ls -la <path>; run id to confirm the user).
- If the directory is enormous, narrow the search with include/exclude glob patterns or reduce the tree depth to stay under the 10MB buffer.
- Run the same ripgrep invocation manually to reproduce: <rgPath> --files --no-ignore --glob '<pattern>' -- '<searchPath>' and inspect the exit code.
- If spawnSync itself failed (result.status === null), check that the @vscode/ripgrep binary path is valid and the binary has execute permissions.
Example fix
// before
const result = spawnSync(rgPath, args, {
encoding: "utf-8",
maxBuffer: 10 * 1024 * 1024,
});
if (result.status > 1) {
throw new Error(result.stderr || `ripgrep exited with code ${result.status}`);
}
// after — handle signal/null-status crashes and surface spawn errors too
const result = spawnSync(rgPath, args, {
encoding: "utf-8",
maxBuffer: 10 * 1024 * 1024,
});
if (result.error) {
throw new Error(`Failed to launch ripgrep: ${result.error.message}`);
}
if (result.signal) {
throw new Error(`ripgrep killed by signal ${result.signal}`);
}
if (result.status > 1) {
throw new Error(result.stderr || `ripgrep exited with code ${result.status}`);
} Defensive patterns
Strategy: try-catch
Validate before calling
const fs = require("fs");
// Validate path before calling the listing tool
if (!fs.existsSync(searchPath)) {
throw new Error(`searchPath does not exist: ${searchPath}`);
}
try { fs.accessSync(searchPath, fs.constants.R_OK); }
catch { throw new Error(`searchPath is not readable: ${searchPath}`); }
// Validate glob patterns are syntactically plausible
for (const p of patterns) {
if (p.includes("{" )) {
const opens = (p.match(/{/g) || []).length;
const closes = (p.match(/}/g) || []).length;
if (opens !== closes) throw new Error(`Unbalanced braces in glob: ${p}`);
}
} Type guard
/** @param {string} p */
function isValidSearchPath(p) {
return typeof p === "string" && p.length > 0 && !p.includes("\0");
} Try / catch
try {
const result = listFilesWithRipgrep({ searchPath, patterns, excludePatterns, maxResults });
// use result.files
} catch (e) {
if (e.message.includes("permission denied")) {
// handle access issue — notify user or fall back
}
logger.error(`File listing failed: ${e.message}`);
return { files: [], error: e.message };
} Prevention
- Validate the searchPath exists and is readable before invoking the tool.
- Limit the directory size searched or use excludePatterns to avoid blowing the 10MB maxBuffer.
- Run ripgrep manually to diagnose recurring failures.
- Monitor result.status === null (killed by signal) separately from numeric exit codes.
When it happens
Trigger: Calling the agent file-listing tool with a searchPath that does not exist, is not readable by the process, contains a path ripgrep cannot traverse, or when the 10MB maxBuffer is exceeded by a very large directory tree. Also triggered by passing malformed glob patterns to --glob that ripgrep rejects.
Common situations: Docker container where the mounted volume has restrictive ownership; searching a node_modules or build output directory with thousands of files blowing the 10MB stdout buffer; searchPath pointing to a deleted or renamed folder; glob syntax like **/*.{js that has an unclosed brace.
Related errors
- search pattern must not start with '-'
- @vscode/ripgrep not installed
- Input file ${inputPath} does not exist.
- Filename is required!
- Invalid path.
AI-assisted analysis of Mintplex-Labs/anything-llm@526360e320 (2026-08-13).
Data as JSON: /api/errors/b019ec9c6ac023af.
Report an issue: GitHub.