From 5d282f95a0177ae70213f54c71319074caec6f9b Mon Sep 17 00:00:00 2001 From: Brian Date: Tue, 12 May 2026 20:32:00 -0500 Subject: [PATCH] fix(installer): throw descriptive error when module definition missing after clone When a stable tag predates a module restructure (e.g. baut v1.14.0 had payload/source dirs, but the registry pointed to skills/module.yaml which only exists on main), findExternalModuleSource silently returned the configured but non-existent path. This caused a confusing ENOENT inside getFileList/copyModuleWithFiltering rather than a clear error. Now throws with the version that was cloned and a --next hint when the install channel was stable, so users know exactly how to recover. Closes #2372 --- tools/installer/modules/external-manager.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/tools/installer/modules/external-manager.js b/tools/installer/modules/external-manager.js index 7d2add4fb..f65265606 100644 --- a/tools/installer/modules/external-manager.js +++ b/tools/installer/modules/external-manager.js @@ -524,8 +524,22 @@ class ExternalModuleManager { return path.dirname(rootCandidate); } - // Nothing found: return configured path (preserves old behavior for error messaging) - return path.dirname(configuredPath); + // Nothing found: the cloned ref does not contain a recognizable module structure. + // This happens when a stable tag predates a module restructure (e.g. the repo + // moved files from payload/ to skills/ after the tag was cut). Returning a + // non-existent path silently causes a confusing ENOENT deep inside copyModuleWithFiltering; + // throw a descriptive error here instead so the user knows what happened and how to recover. + const resolution = ExternalModuleManager._resolutions.get(moduleCode); + const versionHint = resolution?.version ? `version ${resolution.version}` : 'the cloned version'; + const channelHint = + resolution?.channel === 'stable' + ? ` Try reinstalling with \`--next=${moduleCode}\` to use the latest main branch instead.` + : ''; + throw new Error( + `Module '${moduleCode}' was downloaded but its module definition was not found. ` + + `Expected '${moduleDefinitionPath}' to exist in ${versionHint}, but it is missing. ` + + `The repository may have been restructured after this release was tagged.${channelHint}`, + ); } cachedModules = null; }