From efdba59e49ccdb3d4ec353196f04795fccaf45ff Mon Sep 17 00:00:00 2001 From: Dale Yarborough Date: Thu, 26 Feb 2026 21:16:28 -0600 Subject: [PATCH] fix(plugins): clear error when npm package not found (Closes #24993) (#25073) --- src/infra/install-source-utils.test.ts | 18 ++++++++++++++++++ src/infra/install-source-utils.ts | 9 ++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/infra/install-source-utils.test.ts b/src/infra/install-source-utils.test.ts index b9f245510c2..64cb804210f 100644 --- a/src/infra/install-source-utils.test.ts +++ b/src/infra/install-source-utils.test.ts @@ -244,6 +244,24 @@ describe("packNpmSpecToArchive", () => { }); }); + it("returns friendly error for 404 (package not on npm)", async () => { + const cwd = await createFixtureDir(); + mockPackCommandResult({ + stdout: "", + stderr: "npm error code E404\nnpm error 404 '@openclaw/whatsapp@*' is not in this registry.", + code: 1, + }); + + const result = await runPack("@openclaw/whatsapp", cwd); + + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.error).toContain("Package not found on npm"); + expect(result.error).toContain("@openclaw/whatsapp"); + expect(result.error).toContain("docs.openclaw.ai/tools/plugin"); + } + }); + it("returns explicit error when npm pack produces no archive name", async () => { const cwd = await createFixtureDir(); mockPackCommandResult({ diff --git a/src/infra/install-source-utils.ts b/src/infra/install-source-utils.ts index 206711db2fc..fce33b61979 100644 --- a/src/infra/install-source-utils.ts +++ b/src/infra/install-source-utils.ts @@ -207,7 +207,14 @@ export async function packNpmSpecToArchive(params: { }, ); if (res.code !== 0) { - return { ok: false, error: `npm pack failed: ${res.stderr.trim() || res.stdout.trim()}` }; + const raw = res.stderr.trim() || res.stdout.trim(); + if (/E404|is not in this registry/i.test(raw)) { + return { + ok: false, + error: `Package not found on npm: ${params.spec}. See https://docs.openclaw.ai/tools/plugin for installable plugins.`, + }; + } + return { ok: false, error: `npm pack failed: ${raw}` }; } const parsedJson = parseNpmPackJsonOutput(res.stdout || "");