Summary
elastic extension install <bad-source> dumps a raw Node.js stack trace to the terminal instead of a clean user-facing error message.
Steps to reproduce
elastic extension install bad-source
Actual behaviour
file:///dist/extension/installer.js:69
throw new Error(`Invalid GitHub source "bad-source". Use github:owner/repo or owner/repo.`);
^
Error: Invalid GitHub source "bad-source". ...
at parseSource (installer.js:69)
at installExtension (installer.js:190)
at handleInstall (register.js:41)
...
Node.js v24.9.0
Expected behaviour
Error: Invalid GitHub source "bad-source". Use github:owner/repo or owner/repo.
Root cause
handleInstall (and handleUpgrade, handleRemove) in src/extension/register.ts do not wrap calls to installExtension / upgradeExtension / uninstallExtension in a try-catch. The factory only converts { error: { code } } return values to clean errors; thrown exceptions propagate uncaught to Node.js.
Fix
Wrap installer calls in register.ts to return structured error objects instead of throwing:
async function handleInstall(parsed: { arg?: string }): Promise<JsonValue> {
const source = parsed.arg?.trim()
if (!source) return { error: { code: 'missing_source', message: '...' } }
try {
const entry = await installExtension(source)
return { installed: true, ...entry } as unknown as JsonValue
} catch (err: unknown) {
return {
error: {
code: 'install_failed',
message: err instanceof Error ? err.message : String(err),
},
} as unknown as JsonValue
}
}
Same pattern needed for handleUpgrade and handleRemove.
Summary
elastic extension install <bad-source>dumps a raw Node.js stack trace to the terminal instead of a clean user-facing error message.Steps to reproduce
Actual behaviour
Expected behaviour
Root cause
handleInstall(andhandleUpgrade,handleRemove) insrc/extension/register.tsdo not wrap calls toinstallExtension/upgradeExtension/uninstallExtensionin a try-catch. The factory only converts{ error: { code } }return values to clean errors; thrown exceptions propagate uncaught to Node.js.Fix
Wrap installer calls in
register.tsto return structured error objects instead of throwing:Same pattern needed for
handleUpgradeandhandleRemove.