#16725·conda

Deconflict Overlapping Error Type Usage

Author: ryanskeithCreated Sep 18, 2026Updated Sep 18, 2026
Labelstype::feature

Checklist

  • I added a descriptive title
  • I searched open requests and couldn't find a duplicate

What is the idea?

While documenting Group A errors for #16663 (epic #16274), the exception taxonomy turned out to carry more types than there are actual user situations. Four exception names currently cover three stories, and one of them prints the wrong story depending on a constructor argument and also covers two different situations.

There should be one-- and preferably only one --obvious way to do it.

This issue is for agreeing on a target shape to reduce options and disambiguate situations of when to use which error.

Current shape

Type Raised from User situation
PackageNotInstalledError update, list --full-name Not in this environment
PackagesNotFoundInPrefixError remove (+ conversions) Not in this environment
PackagesNotFoundError (base) search --envs Not in any environment
PackagesNotFoundError (libmamba) libmamba install (when channels is supplied) Not in configured channels
PackagesNotFoundError (libmamba) libmamba remove path (when no channel is supplied) Not in environment
PackagesNotFoundInChannelsError create/install/update/search/clone/--revision Not in configured channels

The overlaps

1. PackagesNotFoundInPrefixError is a documented alias of PackageNotInstalledError. Same meaning, same message branch — the child, PackagesNotFoundInPrefixError, just assumes an iterable so the multi-package text is used. PackageNotInstalledError also handles this case. Interesting enough PackageNotInstalledError inherits from PackagesNotFoundError which seems weird to go from plural to singular.

2. The identity of base type, PackagesNotFoundError, depends on channel_urls. PackagesNotFoundError renders "not available from current channels" when channel_urls is set and "missing from the target environment" when it isn't. So PackagesNotFoundInChannelsError constructed with an empty channel list prints a prefix-miss message under a channel-miss type name. So the use can be used to either fill the Packages not in environment (or environments see next point) and if a package isn't found in the current channel configuration. It is used both ways in conda-libmamba-solver and also has code in conda to recast it to PackagesNotFoundInChannelsError if it has been raised during transaction handling. Also even in its own documentation it states:

    """Base error for missing packages.

    Prefer raising one of the more specific subclasses:

    - :class:`PackagesNotFoundInChannelsError` – packages unavailable in channels.
    - :class:`PackageNotInstalledError` – packages missing from a target prefix.
    """

3. search --envs uses PackagesNotFoundError type no channels mode for a local-env miss. main_search.py:213 raises the PackagesNotFoundError with no channels, so it inherits the prefix wording, "The following packages are missing from the target environment: <package list". It should be more along the lines of "Not found in any local environment" as a third distinct situation.

Why is this needed?

There shouldn't be Errors that can serve two purposes and having specialized cases for iterables is too special. Errors should be able to handle one or multiple cases as is already done.

What should happen?

Proposal

Collapse to three types, one per user situation:

Situation Type
Not in this environment Package(s)NotInstalledError
Not in any local environment new/renamed type for search --envs
Not in the configured channels PackagesNotFoundInChannelsError

Strategy:

  1. Fix known callers of PackagesNotFoundError (i.e. in conda-libmamba-solver) and pass the appropriate error case.
  2. Move PackagesNotFoundError to a pure base class that does not broadcast any message and protects against doing so.
  • It's only job is to hold packages.
  • PackagesNotFoundInChannelsError owns channels case
  • PackageNotInstalledError and PackagesNotFoundInPrefixError replacement will own local case
  1. Deprecate PackageNotInstalledError and PackagesNotFoundInPrefixError while creating the PackagesNotInstalledError in the style of PackagesNotFoundInPrefixError that accepts prefix for proper identification of environment. PackagesNotInstalledError should handle singular and multiple cases.
  2. Create new type of error that handles the Packages not found in any local environment case. It's one job is to be raised in the search --envs case. It is the local equivalent of NotFoundInChannels.

Dependency order:

  • Immediately
    • The new errors could be created immediately (part of 3 and 4)
    • Fixes to base class being called in conda-libmamba-solver and others (1)
  • Longer term
    • Move of PackagesNotFoundError as non callable base class (2)
      • Need to deprecate notice the using channels as part of the PackagesNotFoundError instance creation.
    • Start deprecation notices for PackageNotInstalledError and PackagesNotFoundInPrefixError. (3)

Additional Context

No response