-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Surface hooks.py install errors in marketplace UI #1380
Description
Problem
When installing a plugin via the marketplace, if hooks.py:install() or initialize.py fails (e.g., network timeout during pip install, transient package registry error, DNS failure in container), the plugin appears "installed successfully" in the UI — but required dependencies are missing and the plugin is broken at runtime.
The root cause is that _plugin_installer/helpers/install.py calls run_install_hook(), which invokes hooks.py:install(). Inside hooks.py, initialize.py typically runs via subprocess.run(..., capture_output=True) with a try/except that logs a warning but doesn't propagate the failure to the UI. The user has no indication that post-install steps failed.
Example
A plugin that requires python-telegram-bot via initialize.py:
- User installs plugin from marketplace → UI shows "Installed successfully"
initialize.pyfails silently (e.g., pip timeout)- User tries to use the plugin →
ModuleNotFoundError: No module named 'telegram' - User has no idea what went wrong or how to fix it
Suggestion
Surface post-install hook errors visibly in the marketplace UI. For example:
- If
run_install_hook()raises, show a warning banner: "Plugin installed but post-install setup encountered errors. Try clicking Init to re-run setup, or check logs." - Alternatively, return a
warningsfield in the install response that the UI can display alongside the success message - Consider also showing the Init button more prominently for plugins that have an
initialize.py, so users can easily re-run dependency installation
Context
We discovered this while testing several community plugins across A0 v1.3. As a workaround, our plugins now include runtime auto-install fallbacks (try importing, catch ModuleNotFoundError, pip install on the fly). But this shouldn't be necessary — the framework should communicate install failures clearly.
Affected flow
install_from_git() / install_uploaded_zip() → run_install_hook() → plugins.call_plugin_hook(plugin_name, "install") → plugin's hooks.py:install() → subprocess.run([python, "initialize.py"], capture_output=True) — failure here is silently caught.