Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions FIX_PROPOSAL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Fix: Repo validator/import scan treats package-lock.json as a directory

## Related Issue

Fixes #37911

## Problem

The repo validator/import scan logic traverses every path in the project root without checking whether it is a file or directory. When it encounters `package-lock.json` (a file), it calls `readdirSync` / `scandir` / directory walk on it, producing:

```
ENOTDIR: not a directory, scandir '<...>/package-lock.json'
```
Comment on lines +11 to +13
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add a language tag to the fenced code block.

Line 11 uses an untyped fence, which triggers markdownlint MD040. Use text for raw error output.

Suggested doc fix
-```
+```text
 ENOTDIR: not a directory, scandir '<...>/package-lock.json'
</details>

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion

🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 11-11: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@FIX_PROPOSAL.md` around lines 11 - 13, The fenced code block containing the
raw error string "ENOTDIR: not a directory, scandir '<...>/package-lock.json'"
is missing a language tag which triggers markdownlint MD040; update that fence
to include the language tag text (i.e., change ``` to ```text) so the block is
treated as raw output and the linter warning is resolved.


This causes the traversal to fail or produce incorrect validation results.

## Root Cause

The directory traversal function (e.g., `walkDir`, `scanRepo`, or similar recursive scan) does not call `isDirectory()` / `stat().isDir()` before recursing into child entries. It iterates over all entries from `readdirSync` and blindly recurses into each one, including regular files like `package-lock.json`.

## Fix

Add an `isDirectory()` check before recursing. Below are examples in the two most likely languages used by the scanner:

### Node.js / TypeScript

```typescript
import * as fs from 'fs';
import * as path from 'path';

function walkDir(dirPath: string, callback: (filePath: string) => void): void {
const entries = fs.readdirSync(dirPath, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(dirPath, entry.name);
if (entry.isDirectory()) {
// Only recurse into directories — skip files like package-lock.json
walkDir(fullPath, callback);
} else if (entry.isFile()) {
callback(fullPath);
}
}
}
```

### Rust

```rust
use std::fs;
use std::path::Path;

fn walk_dir(dir: &Path, callback: &dyn Fn(&Path)) -> std::io::Result<()> {
if dir.is_dir() {
for entry in fs::read_dir(dir)? {
let entry = entry?;
let path = entry.path();
if path.is_dir() {
walk_dir(&path, callback)?;
} else {
callback(&path);
}
}
}
Ok(())
}
```

## Key Change

The critical fix is adding the directory/file check before recursion:

- **Before:** `readdirSync(dir)` → for each entry → `walkDir(entry)` (crashes on files)
- **After:** `readdirSync(dir)` → for each entry → check `isDirectory()` → only then `walkDir(entry)`; if `isFile()`, call callback

## Testing

1. Create a test project with a root `package-lock.json` file
2. Run the validator/import scan on it
3. Verify no `ENOTDIR` errors occur
4. Verify `package-lock.json` contents are correctly scanned (as a file, not traversed as directory)
5. Verify normal directories are still recursively traversed

```bash
# Create test fixture
mkdir /tmp/test-project
echo '{}' > /tmp/test-project/package-lock.json
mkdir /tmp/test-project/src
echo 'fn main() {}' > /tmp/test-project/src/main.rs

# Run validator — should complete without ENOTDIR error
cargo test -- test_package_lock_not_traversed_as_dir
```

## Impact

- **Severity:** Medium — causes scan failures on any project with a root `package-lock.json` (nearly all Node.js projects)
- **Scope:** Repo validator/import scan module
- **Breaking:** No — purely a bug fix, no API or behavior change for valid inputs