Bug: deep content search discards all ripgrep matches because ./ is treated as a hidden path
Bug description
Deep content search is enabled and ripgrep is available, but searches inside file contents return no results. Filename searches work correctly.
The issue is caused by the path returned by ripgrep when searching from the current directory. ripgrep returns paths with a ./ prefix, for example:
./FSQ-001-LUM-5-20260627.md
The search route passes that path directly to hiddenFiles.isHiddenPath(). The leading . is interpreted as a hidden-file prefix, so every content match is discarded before the access check and response formatting.
Version and environment
- NextExplorer:
v2.2.7
- Repository commit tested:
bac2e07
- Deployment: Docker
- Architecture: Linux ARM64 /
aarch64
- Search configuration:
SEARCH_DEEP=true
SEARCH_RIPGREP=true
- ripgrep:
15.1.0
Steps to reproduce
-
Enable deep search:
SEARCH_DEEP=true
SEARCH_RIPGREP=true
-
Mount a directory containing a Markdown file. For example:
HermesReports/FSQ-001-LUM-5-20260627.md
-
Put a unique term in the file, such as IBOP.
-
Search through the API:
GET /api/search?q=IBOP&path=HermesReports
-
Actual result:
-
Search by filename instead, for example FSQ. Filename results are returned correctly.
Expected behavior
The content search should return the matching Markdown file, including the matched line and line number.
Direct ripgrep evidence
Inside the same container and as the application user, ripgrep finds the match:
./FSQ-001-LUM-5-20260627.md:16:... Saver Sub ... IBOP mecánico ...
The API returns no results because the match is discarded by the hidden-path check.
Root cause
In backend/src/routes/search.js, the content-search path currently performs the hidden-file check on the raw ripgrep path:
const filePath = data.data?.path?.text;
if (!filePath) continue;
if (!includeHiddenFiles && hiddenFiles.isHiddenPath(filePath)) continue;
For a normal file returned as ./file.md, this incorrectly treats the . from ./ as a hidden-file marker.
Proposed fix
Normalize the relative path before checking whether it is hidden:
const filePath = data.data?.path?.text;
if (!filePath) continue;
-if (!includeHiddenFiles && hiddenFiles.isHiddenPath(filePath)) continue;
+const normalizedFilePath = filePath.replace(/^\.\/+/, '');
+if (!includeHiddenFiles && hiddenFiles.isHiddenPath(normalizedFilePath)) continue;
An equivalent normalization using the existing path utility would also be acceptable.
Verification
I built an ARM64 test image with this two-line change and reproduced the same API request. It returned:
{
"items": [
{
"name": "FSQ-001-LUM-5-20260627.md",
"path": "HermesReports",
"kind": "file",
"matchLineNumber": 16
}
]
}
The production container now uses a locally built image containing this fix, and its health check remains healthy.
Additional notes
This affects content matches returned by ripgrep. Filename matching is unaffected. The bug is reproducible with Markdown files and should also affect other text-searchable file types.
Bug: deep content search discards all ripgrep matches because
./is treated as a hidden pathBug description
Deep content search is enabled and
ripgrepis available, but searches inside file contents return no results. Filename searches work correctly.The issue is caused by the path returned by
ripgrepwhen searching from the current directory.ripgrepreturns paths with a./prefix, for example:The search route passes that path directly to
hiddenFiles.isHiddenPath(). The leading.is interpreted as a hidden-file prefix, so every content match is discarded before the access check and response formatting.Version and environment
v2.2.7bac2e07aarch64SEARCH_DEEP=trueSEARCH_RIPGREP=true15.1.0Steps to reproduce
Enable deep search:
Mount a directory containing a Markdown file. For example:
Put a unique term in the file, such as
IBOP.Search through the API:
Actual result:
{"items":[]}Search by filename instead, for example
FSQ. Filename results are returned correctly.Expected behavior
The content search should return the matching Markdown file, including the matched line and line number.
Direct ripgrep evidence
Inside the same container and as the application user, ripgrep finds the match:
The API returns no results because the match is discarded by the hidden-path check.
Root cause
In
backend/src/routes/search.js, the content-search path currently performs the hidden-file check on the raw ripgrep path:For a normal file returned as
./file.md, this incorrectly treats the.from./as a hidden-file marker.Proposed fix
Normalize the relative path before checking whether it is hidden:
An equivalent normalization using the existing path utility would also be acceptable.
Verification
I built an ARM64 test image with this two-line change and reproduced the same API request. It returned:
{ "items": [ { "name": "FSQ-001-LUM-5-20260627.md", "path": "HermesReports", "kind": "file", "matchLineNumber": 16 } ] }The production container now uses a locally built image containing this fix, and its health check remains healthy.
Additional notes
This affects content matches returned by ripgrep. Filename matching is unaffected. The bug is reproducible with Markdown files and should also affect other text-searchable file types.