← Back to PRs

#12939: fix(memory): strip null bytes from workspace paths causing ENOTDIR

by omair445 open 2026-02-09 23:49 View on GitHub →
agents size: XS
## Summary Fixes QMD boot failure where `MEMORY.md` path contains a trailing null byte (`\0`), causing `ENOTDIR` when the indexer tries to open the file. ## Problem Some config sources or file system operations introduce trailing null bytes in workspace directory paths. When QMD passes these paths to `fs.open()`, Node rejects with `ENOTDIR`: ``` ENOTDIR: not a directory, open '/home/cosmo/clawd/MEMORY.md\^@' ``` ## Changes **`src/agents/agent-scope.ts`** - `resolveAgentWorkspaceDir()` now strips null bytes from resolved paths (root fix) **`src/memory/qmd-manager.ts`** - QMD manager constructor strips null bytes from workspace dir (defense-in-depth) **`src/memory/backend-config.ts`** - `resolveDefaultCollections()` strips null bytes before building collection paths (defense-in-depth) **Tests:** - `src/agents/agent-scope.test.ts` — new test verifying null byte stripping - `src/memory/backend-config.test.ts` — new test verifying collection paths are clean ## Testing - All 17 agent-scope + backend-config tests pass ✅ - 🤖 AI-assisted (Claude) — fully tested, all changes understood Closes #12919 <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR addresses a boot-time QMD failure where workspace paths can contain trailing NUL ("\0") bytes, causing Node `fs.open()`/path operations to throw `ENOTDIR`. Changes include: - Sanitizing agent workspace directory resolution by stripping `\0` bytes in `resolveAgentWorkspaceDir()`. - Additional defense-in-depth sanitization in the QMD manager constructor and when building default QMD collection roots. - New tests ensuring configured workspace paths and default collection paths do not contain `\0`. Overall, the approach fits the codebase by centralizing the main fix in agent workspace resolution and adding targeted safeguards around QMD’s path usage, but there are still a couple call paths where `workspaceDir` can remain unsanitized (default workspace branch and custom QMD paths). <h3>Confidence Score: 3/5</h3> - Reasonably safe but still leaves known null-byte path cases unsanitized in some branches. - Core sanitization is implemented and tests cover configured workspace + default collections, but the default workspace path branch (via OPENCLAW_HOME) is not sanitized and relative custom QMD paths/session export dirs can still inherit a NUL-containing workspace base. Those gaps mean the reported ENOTDIR class of failure can still occur for some configurations. - src/agents/agent-scope.ts, src/memory/backend-config.ts <!-- greptile_other_comments_section --> <sub>(5/5) You can turn off certain types of comments like style [here](https://app.greptile.com/review/github)!</sub> <!-- /greptile_comment -->

Most Similar PRs