Public bug reported:

Package.mark_install(auto_fix=True) fails on a dependency set that apt-
get install solves with the same libapt. The resolver is built only
after MarkInstall has already chosen a provider. apt-get creates the
ProblemResolver, protects the requested package, and only then marks.

Affected code in python3-apt 2.7.7ubuntu5.3 (apt 2.8.3, Ubuntu 24.04.5),
apt/package.py:

self._pcache.cache_pre_change()
self._pcache._depcache.mark_install(self._pkg, auto_inst, from_user)
if auto_fix and self._pcache._depcache.broken_count > 0:
    fixer = apt_pkg.ProblemResolver(self._pcache._depcache)
    fixer.clear(self._pkg)
    fixer.protect(self._pkg)
    fixer.resolve(True)
self._pcache.cache_post_change()

Same code is in main (https://salsa.debian.org/apt-team/python-
apt/-/blob/main/apt/package.py#L1434-1458)

MarkInstall records provider choices only while a ProblemResolver is
already attached. Created afterwards, Resolve() treats the chosen
provider as fixed. It drops another dependency instead of trying the
alternative, then stops because the requested package is protected. The
error is apt_pkg.Error: E:Unable to correct problems, you have held
broken packages. Nothing is held.

Reproduction, empty apt root, Ubuntu 26.04 (resolute) main and universe,
observed 2026-10-14:

libvirt-daemon-driver-qemu depends on qemu-kvm | qemu-system and on
ubuntu-virt. qemu-kvm is provided by qemu-system-x86-hwe
1:10.2.1+ds-1ubuntu4.3 and by qemu-system-x86 1:10.2.1+ds-1ubuntu3.2.
MarkInstall takes the higher HWE provider. That package depends on
ubuntu-virt-hwe, which conflicts with ubuntu-virt.

apt-get -s install libvirt-daemon-system on that root succeeds and
selects qemu-system-x86. pkg.mark_install() raises the error above and
leaves libvirt-daemon-driver-qemu unmarked.

Creating the resolver and calling protect() before mark_install, then
resolve(True) only if broken_count > 0, resolves the same cache with
broken_count == 0 and qemu-system-x86 selected. resolve(True) versus
resolve(False) does not matter. cache_pre_change() and
cache_post_change() should stay around the operation; they only emit
callbacks.

Suggested order:

self._pcache.cache_pre_change()
fixer = apt_pkg.ProblemResolver(self._pcache._depcache)
fixer.clear(self._pkg)
fixer.protect(self._pkg)
self._pcache._depcache.mark_install(self._pkg, auto_inst, from_user)
if auto_fix and self._pcache._depcache.broken_count > 0:
    fixer.resolve(True)
self._pcache.cache_post_change()

** Affects: python-apt (Ubuntu)
     Importance: Undecided
         Status: New

** Description changed:

  Package.mark_install(auto_fix=True) fails on a dependency set that apt-
  get install solves with the same libapt. The resolver is built only
  after MarkInstall has already chosen a provider. apt-get creates the
  ProblemResolver, protects the requested package, and only then marks.
  
  Affected code in python3-apt 2.7.7ubuntu5.3 (apt 2.8.3, Ubuntu 24.04.5),
  apt/package.py:
  
- 
  self._pcache.cache_pre_change()
  self._pcache._depcache.mark_install(self._pkg, auto_inst, from_user)
  if auto_fix and self._pcache._depcache.broken_count > 0:
-     fixer = apt_pkg.ProblemResolver(self._pcache._depcache)
-     fixer.clear(self._pkg)
-     fixer.protect(self._pkg)
-     fixer.resolve(True)
+     fixer = apt_pkg.ProblemResolver(self._pcache._depcache)
+     fixer.clear(self._pkg)
+     fixer.protect(self._pkg)
+     fixer.resolve(True)
  self._pcache.cache_post_change()
- MarkInstall records provider choices only while a ProblemResolver is already 
attached. Created afterwards, Resolve() treats the chosen provider as fixed. It 
drops another dependency instead of trying the alternative, then stops because 
the requested package is protected. The error is apt_pkg.Error: E:Unable to 
correct problems, you have held broken packages. Nothing is held.
+ 
+ MarkInstall records provider choices only while a ProblemResolver is
+ already attached. Created afterwards, Resolve() treats the chosen
+ provider as fixed. It drops another dependency instead of trying the
+ alternative, then stops because the requested package is protected. The
+ error is apt_pkg.Error: E:Unable to correct problems, you have held
+ broken packages. Nothing is held.
  
  Reproduction, empty apt root, Ubuntu 26.04 (resolute) main and universe,
  observed 2026-10-14:
  
  libvirt-daemon-driver-qemu depends on qemu-kvm | qemu-system and on
  ubuntu-virt. qemu-kvm is provided by qemu-system-x86-hwe
  1:10.2.1+ds-1ubuntu4.3 and by qemu-system-x86 1:10.2.1+ds-1ubuntu3.2.
  MarkInstall takes the higher HWE provider. That package depends on
  ubuntu-virt-hwe, which conflicts with ubuntu-virt.
  
  apt-get -s install libvirt-daemon-system on that root succeeds and
  selects qemu-system-x86. pkg.mark_install() raises the error above and
  leaves libvirt-daemon-driver-qemu unmarked.
  
  Creating the resolver and calling protect() before mark_install, then
  resolve(True) only if broken_count > 0, resolves the same cache with
  broken_count == 0 and qemu-system-x86 selected. resolve(True) versus
  resolve(False) does not matter. cache_pre_change() and
  cache_post_change() should stay around the operation; they only emit
  callbacks.
  
  Suggested order:
  
- 
  self._pcache.cache_pre_change()
  fixer = apt_pkg.ProblemResolver(self._pcache._depcache)
  fixer.clear(self._pkg)
  fixer.protect(self._pkg)
  self._pcache._depcache.mark_install(self._pkg, auto_inst, from_user)
  if auto_fix and self._pcache._depcache.broken_count > 0:
-     fixer.resolve(True)
+     fixer.resolve(True)
  self._pcache.cache_post_change()

** Description changed:

  Package.mark_install(auto_fix=True) fails on a dependency set that apt-
  get install solves with the same libapt. The resolver is built only
  after MarkInstall has already chosen a provider. apt-get creates the
  ProblemResolver, protects the requested package, and only then marks.
  
  Affected code in python3-apt 2.7.7ubuntu5.3 (apt 2.8.3, Ubuntu 24.04.5),
  apt/package.py:
  
  self._pcache.cache_pre_change()
  self._pcache._depcache.mark_install(self._pkg, auto_inst, from_user)
  if auto_fix and self._pcache._depcache.broken_count > 0:
      fixer = apt_pkg.ProblemResolver(self._pcache._depcache)
      fixer.clear(self._pkg)
      fixer.protect(self._pkg)
      fixer.resolve(True)
  self._pcache.cache_post_change()
+ 
+ Same code is in main (https://salsa.debian.org/apt-team/python-
+ apt/-/blob/main/apt/package.py#L1434-1458)
  
  MarkInstall records provider choices only while a ProblemResolver is
  already attached. Created afterwards, Resolve() treats the chosen
  provider as fixed. It drops another dependency instead of trying the
  alternative, then stops because the requested package is protected. The
  error is apt_pkg.Error: E:Unable to correct problems, you have held
  broken packages. Nothing is held.
  
  Reproduction, empty apt root, Ubuntu 26.04 (resolute) main and universe,
  observed 2026-10-14:
  
  libvirt-daemon-driver-qemu depends on qemu-kvm | qemu-system and on
  ubuntu-virt. qemu-kvm is provided by qemu-system-x86-hwe
  1:10.2.1+ds-1ubuntu4.3 and by qemu-system-x86 1:10.2.1+ds-1ubuntu3.2.
  MarkInstall takes the higher HWE provider. That package depends on
  ubuntu-virt-hwe, which conflicts with ubuntu-virt.
  
  apt-get -s install libvirt-daemon-system on that root succeeds and
  selects qemu-system-x86. pkg.mark_install() raises the error above and
  leaves libvirt-daemon-driver-qemu unmarked.
  
  Creating the resolver and calling protect() before mark_install, then
  resolve(True) only if broken_count > 0, resolves the same cache with
  broken_count == 0 and qemu-system-x86 selected. resolve(True) versus
  resolve(False) does not matter. cache_pre_change() and
  cache_post_change() should stay around the operation; they only emit
  callbacks.
  
  Suggested order:
  
  self._pcache.cache_pre_change()
  fixer = apt_pkg.ProblemResolver(self._pcache._depcache)
  fixer.clear(self._pkg)
  fixer.protect(self._pkg)
  self._pcache._depcache.mark_install(self._pkg, auto_inst, from_user)
  if auto_fix and self._pcache._depcache.broken_count > 0:
      fixer.resolve(True)
  self._pcache.cache_post_change()

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2170811

Title:
  Package.mark_install creates the ProblemResolver after MarkInstall, so
  a bad virtual provider cannot be undone

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/python-apt/+bug/2170811/+subscriptions


-- 
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to