From b45f2c0b9e62119bd04d52b75a8da336173d92d9 Mon Sep 17 00:00:00 2001 From: Dotta Date: Wed, 22 Jul 2026 19:44:17 +0000 Subject: [PATCH] fix(doctor): ignore empty managed install stores Co-Authored-By: Paperclip --- cli/src/__tests__/managed-install-check.test.ts | 13 +++++++++++++ cli/src/checks/managed-install-check.ts | 10 ++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/cli/src/__tests__/managed-install-check.test.ts b/cli/src/__tests__/managed-install-check.test.ts index 379fba77314..457dbc1c6d2 100644 --- a/cli/src/__tests__/managed-install-check.test.ts +++ b/cli/src/__tests__/managed-install-check.test.ts @@ -72,4 +72,17 @@ describe("managed install doctor checks", () => { expect.objectContaining({ name: "Managed install", status: "pass" }), ]); }); + + it("ignores an empty installs directory left by a harmless lock lifecycle", () => { + const root = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-install-doctor-")); + const paths = resolveInstallStorePaths({ + paperclipHome: path.join(root, ".paperclip"), + homeDir: root, + }); + fs.mkdirSync(paths.installsRoot, { recursive: true }); + + expect(managedInstallChecks(paths)).toEqual([ + expect.objectContaining({ name: "Managed install", status: "pass" }), + ]); + }); }); diff --git a/cli/src/checks/managed-install-check.ts b/cli/src/checks/managed-install-check.ts index 141b6ebadec..025f1bf33f3 100644 --- a/cli/src/checks/managed-install-check.ts +++ b/cli/src/checks/managed-install-check.ts @@ -17,13 +17,19 @@ function pathContains(directory: string): boolean { } function hasManagedArtifacts(paths: InstallStorePaths): boolean { - return [ - paths.installsRoot, + const persistentArtifacts = [ paths.manifestPath, paths.markerPath, paths.currentPath, paths.shimPath, ].some((entry) => fs.existsSync(entry)); + if (persistentArtifacts) return true; + try { + return fs.readdirSync(paths.installsRoot).length > 0; + } catch (error) { + if ((error as NodeJS.ErrnoException).code === "ENOENT") return false; + return true; + } } export function nodeRuntimeCheck(): CheckResult {