fix(doctor): warn and continue when cron job store is unreadable (#86… · openclaw/openclaw@c637944
1052326311
·
2026-05-25
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
@@ -24,6 +24,7 @@ Docs: https://docs.openclaw.ai
|
24 | 24 | - Docker E2E: dedupe scheduler lane resources so npm/service package lanes are not over-counted and serialized unnecessarily. |
25 | 25 | - Crabbox: bootstrap Git metadata for sparse remote changed gates so raw synced workspaces can run `pnpm check:changed` from the intended diff. |
26 | 26 | - xAI/LM Studio: avoid buffering ordinary bracketed or `final` prose until stream completion while watching for plain-text tool-call fallbacks. |
| 27 | +- Doctor: warn and continue when the cron job store exists but cannot be read (e.g. owned by another user with `0600` mode inside Docker) so later health checks still run. (#86102) |
27 | 28 | - Discord: suppress a bot's previous reply body and referenced media from prompt context when a user replies to that bot message, while keeping reply metadata for routing. (#86238) Thanks @fuller-stack-dev. |
28 | 29 | - Docker E2E: avoid rebuilding the Control UI twice while preparing the shared OpenClaw package tarball for package-backed scenario runs. |
29 | 30 | - Tests: avoid rebuilding the Control UI twice during the installer Docker smoke now that `pnpm build` includes `ui:build`. |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -566,6 +566,29 @@ describe("maybeRepairLegacyCronStore", () => {
|
566 | 566 | expectNoteContaining("managed dreaming job", "Cron"); |
567 | 567 | expectNoteContaining("Rewrote 1 managed dreaming job", "Doctor changes"); |
568 | 568 | }); |
| 569 | + |
| 570 | +it("warns and continues when the cron job store cannot be read", async () => { |
| 571 | +const storePath = await makeTempStorePath(); |
| 572 | +// Force loadCronStore to throw a non-ENOENT read error by placing a |
| 573 | +// directory where the cron job store file would be. This mirrors the |
| 574 | +// Docker-on-root permission failure reported in #86102 without depending |
| 575 | +// on the test runner's effective uid (root bypasses chmod gates). |
| 576 | +await fs.mkdir(path.dirname(storePath), { recursive: true }); |
| 577 | +await fs.mkdir(storePath); |
| 578 | +const prompter = makePrompter(true); |
| 579 | + |
| 580 | +await expect( |
| 581 | +maybeRepairLegacyCronStore({ |
| 582 | +cfg: { cron: { store: storePath } }, |
| 583 | +options: {}, |
| 584 | + prompter, |
| 585 | +}), |
| 586 | +).resolves.toBeUndefined(); |
| 587 | + |
| 588 | +expect(prompter.confirm).not.toHaveBeenCalled(); |
| 589 | +expectNoteContaining("Unable to read cron job store at", "Cron"); |
| 590 | +expectNoteContaining("later health checks will continue", "Cron"); |
| 591 | +}); |
569 | 592 | }); |
570 | 593 | |
571 | 594 | describe("legacy WhatsApp crontab health check", () => { |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -335,7 +335,21 @@ export async function maybeRepairLegacyCronStore(params: {
|
335 | 335 | prompter: Pick<DoctorPrompter, "confirm">; |
336 | 336 | }) { |
337 | 337 | const storePath = resolveCronStorePath(params.cfg.cron?.store); |
338 | | -const store = await loadCronStore(storePath); |
| 338 | +let store: Awaited<ReturnType<typeof loadCronStore>>; |
| 339 | +try { |
| 340 | +store = await loadCronStore(storePath); |
| 341 | +} catch (err) { |
| 342 | +const reason = err instanceof Error ? err.message : String(err); |
| 343 | +note( |
| 344 | +[ |
| 345 | +`Unable to read cron job store at ${shortenHomePath(storePath)}.`, |
| 346 | +`- ${reason}`, |
| 347 | +`Fix the file's permissions or contents and re-run ${formatCliCommand("openclaw doctor")}; later health checks will continue.`, |
| 348 | +].join("\n"), |
| 349 | +"Cron", |
| 350 | +); |
| 351 | +return; |
| 352 | +} |
339 | 353 | const rawJobs = (store.jobs ?? []) as unknown as Array<Record<string, unknown>>; |
340 | 354 | if (rawJobs.length === 0) { |
341 | 355 | return; |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。