Skip to content

fix(plugins): name the plugin that fails to load or activate - #11182

Open
Thanatos9404 wants to merge 2 commits into
python-poetry:mainfrom
Thanatos9404:fix-plugin-error-names
Open

Thanatos9404 wants to merge 2 commits into
python-poetry:mainfrom
Thanatos9404:fix-plugin-error-names

Conversation

@Thanatos9404

Copy link
Copy Markdown

Pull Request Check List

Resolves: #6456

  • Added tests for changed code.
  • Updated documentation for changed code.

When a plugin fails to load or activate, every Poetry command fails with only the plugin's own error. Take the case from the issue: the deprecated poetry-dynamic-versioning-plugin is installed next to poetry-dynamic-versioning, and both register the same command. Then even poetry --help prints just:

The command "dynamic-versioning" already exists.

--no-plugins has been there since 1.2.0 and does get Poetry working again, but nothing points to it or to the plugin at fault. That is what makes it look like Poetry is stuck.

PluginManager now keeps the entry point of each loaded plugin. When ep.load() or a plugin's activate raises, it re-raises with the entry point name and the distribution, and keeps the original exception as the cause. The same setup now prints:

Failed to activate the "poetry-dynamic-versioning" plugin (poetry-dynamic-versioning 0.18.0): The command "dynamic-versioning" already exists.

You can run Poetry with --no-plugins to disable all plugins, for example to update or remove the plugin causing this.

A plugin broken by an upgrade gets the same treatment, for example Failed to load the "my-plugin" plugin: No module named '...'.

Notes on the behaviour:

  • Still a hard failure. I didn't skip the plugin with a warning, since a plugin that silently doesn't run could change what Poetry builds or locks. If you'd rather warn and continue for application plugins, I'm happy to change it.
  • Which plugin is named. With two conflicting plugins, the message names whichever one is activated second, and removing either fixes it. That's why the hint says "the plugin causing this" rather than "this plugin".
  • Traceback kept. With -v, the original traceback is still shown, because the new error is raised from the original.
  • Both plugin groups. The change applies to application plugins and to poetry.plugin plugins activated in Factory.create_poetry.
  • Empty messages. An exception with no message, such as the assert in ApplicationPlugin.activate, is reported by its type name.

Tests:

  • tests/plugins/test_plugin_manager.py checks the message and the cause for an activation error (including an exception without a message) and for an import error while loading.
  • tests/console/test_application.py::test_application_with_failing_plugin registers a plugin with an existing about command, checks the error output, and checks that about --no-plugins still works.

The new tests fail on main and pass with this change. The full test suite passes locally on Windows except test_install_dir_is_symlink and test_python_get_preferred_default, which fail the same way on main. ruff check, ruff format --check (0.16.6) and mypy are clean. docs/plugins.md gets two sentences on recovering with --no-plugins.

#11139 also changes PluginManager.activate, so whichever of the two is merged second will need a small rebase.

When a plugin raised while being loaded or activated, every command
failed with only that error, so a conflicting command name or a broken
import gave no hint which plugin was at fault or that --no-plugins
gets Poetry working again. Re-raise with the entry point name and
distribution, keep the original exception as the cause, and point to
--no-plugins.
sourcery-ai[bot]
sourcery-ai Bot previously approved these changes Oct 31, 2026

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!

Linked issues

#6456 Poetry can get locked into an unusable state with plugins: 'The command "..." already exists' · 1 of 1 met

# Requirement Status Notes
1 Recover Poetry when conflicting plugins make commands fail, without manually removing plugins from its environment. ✅ Met The activation error now identifies the plugin and points to --no-plugins; the application test verifies that the command works with plugins disabled.

Sourcery assessment

Approved.


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
PackageMetadata.get is only in the typing stubs from Python 3.12, so mypy
failed on 3.11. Distribution.name and Distribution.version give the same
values and are what the rest of Poetry already uses.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sourcery assessment

Approved.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant