fix: skip compile cache permission warnings (#76362) (thanks @neeravmakwana)

This commit is contained in:
Ayaan Zaidi
2026-05-05 21:14:32 +05:30
parent 5d03fb2553
commit 77ae06bfaa
3 changed files with 62 additions and 0 deletions

View File

@@ -328,6 +328,7 @@ Docs: https://docs.openclaw.ai
- Config/recovery: chmod restored `openclaw.json` back to owner-only (`0600`) after suspicious-read backup recovery on POSIX hosts, so a previously world-readable config mode cannot persist into a freshly restored credential-bearing config. (#77488) Thanks @drobison00.
- Memory/dreaming: persist last dreaming-ingestion calendar day per daily note in `daily-ingestion.json` so unchanged notes are still re-ingested once per dreaming day for promotion signals toward deep thresholds. Fixes #76225. (#76359) Thanks @neeravmakwana.
- Agents/embed: keep message_end safety delivery armed when a silent text_end chunk produces no block reply, fixing dropped Telegram/forum replies. Fixes #77833. (#77840) Thanks @neeravmakwana.
- Install/postinstall: skip noisy compile-cache prune warnings when `EACCES`/`EPERM` prevent removing shared `/tmp/node-compile-cache` entries owned by another user. Fixes #76353. (#76362) Thanks @RayWoo and @neeravmakwana.
## 2026.5.3-1

View File

@@ -814,6 +814,10 @@ function shouldRunBundledPluginPostinstall(params) {
return true;
}
function isCompileCachePrunePermissionDenied(error) {
return error?.code === "EACCES" || error?.code === "EPERM";
}
export function pruneOpenClawCompileCache(params = {}) {
const env = params.env ?? process.env;
const pathExists = params.existsSync ?? existsSync;
@@ -842,10 +846,16 @@ export function pruneOpenClawCompileCache(params = {}) {
retryDelay: 100,
});
} catch (error) {
if (isCompileCachePrunePermissionDenied(error)) {
continue;
}
log.warn?.(`[postinstall] could not prune OpenClaw compile cache: ${String(error)}`);
}
}
} catch (error) {
if (isCompileCachePrunePermissionDenied(error)) {
continue;
}
log.warn?.(`[postinstall] could not prune OpenClaw compile cache: ${String(error)}`);
}
}

View File

@@ -147,6 +147,57 @@ describe("bundled plugin postinstall", () => {
);
});
it("does not warn when compile-cache pruning hits EACCES or EPERM (shared caches)", () => {
const base = path.join("/tmp", "openclaw-shared-compile-cache");
const dirA = path.join(base, "v22.13.1-x64-efe9a9df-1001");
const dirB = path.join(base, "v22.13.1-x64-efe9a9df-1002");
const warn = vi.fn();
const rmSync = vi.fn((value: string) => {
if (value === dirA) {
throw Object.assign(new Error(`permission denied pruning ${value}`), { code: "EACCES" });
}
if (value === dirB) {
throw Object.assign(new Error(`operation not permitted pruning ${value}`), {
code: "EPERM",
});
}
});
pruneOpenClawCompileCache({
env: { NODE_COMPILE_CACHE: base },
existsSync: vi.fn((value: string) => value === base),
readdirSync: vi.fn(() => [
{ name: path.basename(dirA), isDirectory: () => true },
{ name: path.basename(dirB), isDirectory: () => true },
]),
rmSync,
log: { warn },
});
expect(rmSync).toHaveBeenCalledTimes(2);
expect(warn).not.toHaveBeenCalled();
});
it("does not warn when the compile-cache base directory cannot be listed (EACCES)", () => {
const base = path.join("/tmp", "openclaw-compile-cache-no-list");
const warn = vi.fn();
const rmSync = vi.fn();
const err = Object.assign(new Error(`EACCES: ${base}`), { code: "EACCES" });
pruneOpenClawCompileCache({
env: { NODE_COMPILE_CACHE: base },
existsSync: vi.fn(() => true),
readdirSync: vi.fn(() => {
throw err;
}),
rmSync,
log: { warn },
});
expect(rmSync).not.toHaveBeenCalled();
expect(warn).not.toHaveBeenCalled();
});
it("does not classify published packages with source files as source checkouts", () => {
const packageRoot = "/pkg";
const existingPaths = new Set([