-
-
Notifications
You must be signed in to change notification settings - Fork 52.6k
Description
Summary
On Windows, inbound images sometimes fail with Local media path is not safe to read / path changed during read. The root cause appears to be a false-positive in openVerifiedLocalFile where handle.stat() and fs.lstat() return different dev values on Windows, causing the path-mismatch check to throw even though the file is stable and not a symlink.
Environment
- OS: Windows 11 (NTFS)
- Node: v22.14.0
- OpenClaw: 2026.2.19-2
- Channel: Telegram/WhatsApp inbound images
Repro
- Send an image to the bot (Telegram/WhatsApp).
- OpenClaw logs show:
Local media path is not safe to read: C:\Users\...\.openclaw\media\inbound\...jpg- or
SafeOpenError path-mismatch path changed during read.
- The file exists and can be read normally outside OpenClaw.
Root Cause (suspected)
In src/infra/fs-safe.ts:
const [stat, lstat] = await Promise.all([handle.stat(), fs.lstat(filePath)]);
if (stat.ino !== lstat.ino || stat.dev !== lstat.dev) {
throw new SafeOpenError("path-mismatch", "path changed during read");
}
const realPath = await fs.realpath(filePath);
const realStat = await fs.stat(realPath);
if (stat.ino !== realStat.ino || stat.dev !== realStat.dev) {
throw new SafeOpenError("path-mismatch", "path mismatch");
}On Windows, handle.stat().dev differs from fs.lstat().dev even for the same file. This triggers the error even though the file is stable and not a symlink.
Suggested Fix
Gate dev comparison by platform on Windows, e.g.:
const devMismatch = stat.dev !== lstat.dev && process.platform !== "win32";
if (stat.ino !== lstat.ino || devMismatch) { ... }
const realDevMismatch = stat.dev !== realStat.dev && process.platform !== "win32";
if (stat.ino !== realStat.ino || realDevMismatch) { ... }This keeps the security intent on POSIX while avoiding a false-positive on Windows.
Notes
After applying the above change locally (patched build output), inbound images load successfully and vision works as expected.
If you want, I can send a PR with the exact change.