#934541 aptitude: upgraded a package to experimental without notice, though SolutionCost has "safety" first

Package:
aptitude
Source:
aptitude
Description:
terminal-based package manager
Submitter:
Vincent Lefevre
Date:
2025-08-23 08:47:02 UTC
Severity:
important
#934541#5
Date:
2019-08-12 07:05:20 UTC
From:
To:
In /etc/apt/apt.conf.d/10aptitude I have

Aptitude::ProblemResolver::SolutionCost "safety, removals";

but in an upgrade on 2019-07-08, aptitude upgraded a package to
experimental while I did not ask it explicitly and without any
warning. In the logs of the upgrade:

[UPGRADE] gdal-data:amd64 2.4.0+dfsg-1 -> 3.0.1+dfsg-1~exp1

That was perhaps to satisfy a dependency for the upgrade

[UPGRADE] libgdal20:amd64 2.4.0+dfsg-1+b1 -> 2.4.2+dfsg-1

in case gdal-data:amd64 2.4.2+dfsg-1 was not yet in the archives
(though libgdal20:amd64 2.4.2+dfsg-1 was already there).

But I would have never upgraded if I knew that there was an
experimental package there (I occasionally upgrade packages
to experimental, but only for a specific reason).

#934541#10
Date:
2020-02-24 08:45:46 UTC
From:
To:
This bug still occurs. During an upgrade last month:

Aptitude 0.8.12: log report
Mon, Jan 27 2020 13:16:20 +0100
[...]
[UPGRADE] bash-completion:amd64 1:2.9-1 -> 1:2.10-1
[UPGRADE] dict-wn:amd64 1:3.0-35 -> 1:3.0-36
[UPGRADE] ksh:amd64 2020.0.0-2.1 -> 2020.0.0-4
[UPGRADE] lzip:amd64 1.21-5 -> 1.21-6
[UPGRADE] mksh:amd64 57-4 -> 57-5
[UPGRADE] opera-stable:amd64 66.0.3515.36 -> 66.0.3515.44
[UPGRADE] python-apt:amd64 1.8.5 -> 1.8.6
[UPGRADE] python-apt-common:amd64 1.8.5 -> 1.9.5
[UPGRADE] python3-apt:amd64 1.8.5 -> 1.8.6
[UPGRADE] qpdf:amd64 9.1.0-1 -> 9.1.1-1

but python-apt-common comes from experimental:

python-apt (1.9.5) experimental; urgency=medium

  [ Marc Deslauriers ]
  * SECURITY REGRESSION: crash with ubuntu-release-upgrader (LP: #1860606)
    - apt/cache.py: make allow_unauthenticated argument to
      fetch_archives() optional.

  [ Julian Andres Klode ]
  * Really bump aptdaemon break (to 1.1.1+bzr982-0ubuntu31)

#934541#17
Date:
2020-02-24 09:12:47 UTC
From:
To:
[...]

And note that there is only an unversioned dependency from
python-apt and python3-apt to python-apt-common. Thus there
are 2 (possibly related) issues:

1. A bug in the resolver, which proposed the experimental version,
   though this was not requested by a dependency.

2. A missing warning about the upgrade of an unstable package to
   experimental.

#934541#22
Date:
2025-03-18 14:17:08 UTC
From:
To:
Still the same bug (or similar). A bundle is available at

https://vinc17.net/aptitude-20250318.bundle

for a limited time.

To reproduce, at

#934541#29
Date:
2025-03-18 14:32:45 UTC
From:
To:
[...]

Actually, the '+' over "emacs-gtk" is fine since the proposed
removal is just libtree-sitter0, which is OK.

This is clearer with "examine". When typing '+' over "main":

[...]
    --\ main           The main Debian archive (2)
idA emacs-bin-common -364 kB   1:30.1+1-4               1:30.1+1-4+b1
iB  emacs-gtk                  1:30.1+1-4               1:30.1+1-4
[...]
[1(1)/...] Actions: 1 keep
e: Examine  !: Apply  .: Next  ,: Previous

then 'e' to examine:

#934541#34
Date:
2025-03-21 09:33:15 UTC
From:
To:
I'm afraid there's nobody left who understands the aptitude solver,
could reason whether the behavior is correct given the constraints
or suggest a different setting for SolutionCost that is not prone
to this problem.

I believe you explained the reasoning in your follow up where you
show it takes a lot of tries to get to your expected solution -
the solver might have given up too early and then not seen your
proposed solution yet. It does not claim to yield optimal results,
it by very definition is not able too - the solver is a heuristical
best-search solver, rather than a complete MaxSAT solver, and
it's infeasible to calculate all possible solutions, so it has
to make some cut offs in the search space it considers.

Now one thing to point out is that libtree-sitter0 is still
available in unstable. I don't know about aptitude; but apt
would consider this in its considerations and prefer to
keep libtree-sitter0 around rather than remove it (it may
magically get there by other means).

Building a solver that deals correctly with conflicting information
like this in development releases is pretty hard.

#934541#39
Date:
2025-05-16 11:04:17 UTC
From:
To:
[...]

Perhaps the root cause was not experimental after all, because now
that the experimental version has gone (which is a simpler situation),
aptitude still doesn't want to install the testing/unstable version
as an immediate solution, even with the default SolutionCost.

Confirming that the experimental version has gone:

disset:~> apt-show-versions -a libtree-sitter0.22
No stable version
No stable-updates version
libtree-sitter0.22:amd64 0.22.6-6+b1 testing  ftp.debian.org
libtree-sitter0.22:amd64 0.22.6-6+b1 unstable ftp.debian.org
No experimental version
libtree-sitter0.22:amd64 not installed

First, the test with the command line...

To make things clear, the following is fine (though
libtree-sitter0.22 will be marked as manually installed,
which I do not want):

disset:~> aptitude install -s emacs-gtk libtree-sitter0.22
The following NEW packages will be installed:
  libtree-sitter0.22
The following packages will be REMOVED:
  libtree-sitter0{a}
The following packages will be upgraded:
  emacs emacs-bin-common emacs-common emacs-el emacs-gtk
5 packages upgraded, 1 newly installed, 1 to remove and 2 not upgraded.
Need to get 43.3 MB of archives. After unpacking 3072 B will be freed.

and "aptitude upgrade -s" proposes the same thing, except that
libtree-sitter0.22 will be marked as automatically installed
(libtree-sitter0.22{a}), which is better. However, if one just
wants to upgrade some packages, "aptitude upgrade" is not a
solution in general.

But if I just ask for emacs-gtk, aptitude does not want to
install libtree-sitter0.22 immediately as a dependency:

disset:~> aptitude install -s emacs-gtk
The following packages will be REMOVED:
  libtree-sitter0{u}
The following packages will be upgraded:
  emacs emacs-bin-common emacs-common emacs-el emacs-gtk{b}
5 packages upgraded, 0 newly installed, 1 to remove and 2 not upgraded.
Need to get 43.2 MB of archives. After unpacking 223 kB will be freed.
The following packages have unmet dependencies:
 emacs-gtk : Depends: libtree-sitter0.22 (>= 0.22.4) but it is not going to be installed
The following actions will resolve these dependencies:

     Install the following packages:
1)     libtree-sitter0.22 [0.22.6-6+b1 (testing, unstable)]

Why this "but it is not going to be installed" instead of just
proposing the usual installation of the dependency???

Note that this is the same with the default SolutionCost:

  aptitude install -s \
    -o Aptitude::ProblemResolver::SolutionCost="safety, priority" emacs-gtk

Accepting the solution is OK:

The following NEW packages will be installed:
  libtree-sitter0.22{a}
The following packages will be REMOVED:
  libtree-sitter0{u}
The following packages will be upgraded:
  emacs emacs-bin-common emacs-common emacs-el emacs-gtk
5 packages upgraded, 1 newly installed, 1 to remove and 2 not upgraded.

Now, with the TUI, this is similar when I type '+' over "emacs-gtk":

Some dependencies of emacs-gtk (broken, 1:30.1+1-4) are not satisfied:         ▒
                                                                               ▒
  * emacs-gtk (upgrade, 1:30.1+1-4 -> 1:30.1+1-5) depends on libtree-sitter0.22▒
    (>= 0.22.4)                                                                ▒

and the proposed action:

#934541#44
Date:
2025-08-23 08:44:46 UTC
From:
To:
I think that until now, aptitude upgraded some package to experimental
just in order to resolve a dependency, but several days ago, the
upgraded packages came only from experimental:

===============================================================================

Aptitude 0.8.13: log report
Sat, Aug 16 2025 23:52:19 +0200

  IMPORTANT: this log only lists intended actions; actions which fail
  due to dpkg problems may not be completed.

Will install 2 packages, and remove 0 packages.
98.3 kB of disk space will be used
========================================
[HOLD, DEPENDENCIES] cryptsetup:amd64 2:2.7.5-2
[HOLD, DEPENDENCIES] cryptsetup-bin:amd64 2:2.7.5-2
[HOLD, DEPENDENCIES] firmware-intel-graphics:amd64 20250410-2
[HOLD, DEPENDENCIES] firmware-intel-misc:amd64 20250410-2
[HOLD, DEPENDENCIES] firmware-mediatek:amd64 20250410-2
[HOLD, DEPENDENCIES] firmware-nvidia-graphics:amd64 20250410-2
[HOLD, DEPENDENCIES] gir1.2-gdesktopenums-3.0:amd64 48.0-1
[HOLD, DEPENDENCIES] gnome-robots:amd64 1:41.2-2
[HOLD, DEPENDENCIES] gnome-settings-daemon-common:amd64 48.1-1
[HOLD, DEPENDENCIES] initramfs-tools-bin:amd64 0.148.3
[HOLD, DEPENDENCIES] initramfs-tools-core:amd64 0.148.3
[HOLD, DEPENDENCIES] libfluidsynth3:amd64 2.4.4+dfsg-1
[HOLD, DEPENDENCIES] libpskc0t64:amd64 2.6.13-2
[HOLD, DEPENDENCIES] libsystemd-shared:amd64 257.7-1
[HOLD, DEPENDENCIES] libsystemd0:amd64 257.7-1
[HOLD, DEPENDENCIES] libudev1:amd64 257.7-1
[HOLD, DEPENDENCIES] linux-doc-6.12:amd64 6.12.38-1
[HOLD, DEPENDENCIES] linux-libc-dev:amd64 6.12.38-1
[HOLD, DEPENDENCIES] systemd-cryptsetup:amd64 257.7-1
[HOLD] cryptsetup-initramfs:amd64 2:2.7.5-2
[HOLD] firmware-iwlwifi:amd64 20250410-2
[HOLD] firmware-misc-nonfree:amd64 20250410-2
[HOLD] gnome-backgrounds:amd64 48.2.1-1
[HOLD] gnome-settings-daemon:amd64 48.1-1
[HOLD] gnuplot-data:amd64 6.0.2+dfsg1-2+local1
[HOLD] gnuplot-doc:amd64 6.0.2+dfsg1-2+local1
[HOLD] gnuplot-qt:amd64 6.0.2+dfsg1-2+local1
[HOLD] gsettings-desktop-schemas:amd64 48.0-1
[HOLD] initramfs-tools:amd64 0.148.3
[HOLD] libcryptsetup12:amd64 2:2.7.5-2
[HOLD] libnss-systemd:amd64 257.7-1
[HOLD] libpam-systemd:amd64 257.7-1
[HOLD] libsystemd-dev:amd64 257.7-1
[HOLD] linux-doc:amd64 6.12.38-1
[HOLD] linux-image-amd64:amd64 6.12.38-1
[HOLD] linux-perf:amd64 6.12.38-1
[HOLD] rsync:amd64 3.3.0+ds1-2
[HOLD] systemd:amd64 257.7-1
[HOLD] systemd-sysv:amd64 257.7-1
[HOLD] systemd-timesyncd:amd64 257.7-1
[HOLD] udev:amd64 257.7-1
[UPGRADE] libaqbanking-data:amd64 6.6.0-1 -> 6.6.1-1
[UPGRADE] libaqbanking44:amd64 6.6.0-1 -> 6.6.1-1
========================================

Log complete.

===============================================================================

libaqbanking (6.6.1-1) experimental; urgency=medium

  * New upstream version 6.6.1