[Bug 2125687] Re: Fail to upgrade from plucky to questing in a basic Ubuntu
Simon Poirier
2125687 at bugs.launchpad.net
Fri Apr 17 18:41:14 UTC 2026
** Description changed:
+ [ Impact ]
+
+ * Users of minimal cloud images fail to run do-release-upgrade,
+ during the gpg validation, at the start of the tool.
+ The error can be worked around by manually installing gpg.
+
+ * The dependencies of u-r-u includes gpgv.
+ This replaces call point to gpgv instead of the possibly missing gpg command.
+
+ [ Test Plan ]
+
+ * lxc launch ubuntu-minimal:questing test
+ * lxc exec test -- do-release-upgrade -d
+ * follow interactive prompts
+
+ [ Where problems could occur ]
+
+ * The GPG validation is done at the start of the tool. If call to gpgv
+ was to fail, it would happen before a release upgrade starts and likely
+ show up as a stack trace. Although unsettling, to the user, no harm should
+ have been done yet.
+
+ * It is considered that gpgv, which is already set as a dependency, is a valid
+ drop-in replacement for calling gpg --verify in this context. In the
+ negative, validation of the upgrade tool integrity might be at risk.
+
+ [ Other Info ]
+
+ * The patch is already merged to resolute, but has seen only minimal testing
+ considering resolute doesn't have a release to upgrade to.
+
+ [ Original Description ]
+
Reproducer is very straightforward:
```
podman run -it ubuntu:plucky sh -c "apt update && apt upgrade -y && apt install -y ubuntu-release-upgrader-core && do-release-upgrade -d"
```
This is an interactive session, so make sure to provide answers.
Just when confirming the upgrade, the tool instantly crashes, complaining about a missing `gpg`:
```
Continue [yN] y
Get:1 Upgrade tool signature [833 B]
Get:2 Upgrade tool [966 kB]
Fetched 967 kB in 0s (0 B/s)
/usr/lib/python3/dist-packages/DistUpgrade/DistUpgradeFetcherCore.py:180: Warning: W:Download is performed unsandboxed as root as file 'questing.tar.gz.gpg' couldn't be accessed by user '_apt'. - pkgAcquire::Run (13: Permission denied)
- result = fetcher.run()
+ result = fetcher.run()
authenticate 'questing.tar.gz' against 'questing.tar.gz.gpg'
Traceback (most recent call last):
- File "/usr/bin/do-release-upgrade", line 229, in <module>
- fetcher.run()
- ~~~~~~~~~~~^^
- File "/usr/lib/python3/dist-packages/DistUpgrade/DistUpgradeFetcherCore.py", line 215, in run
- if not self.authenticate():
- ~~~~~~~~~~~~~~~~~^^
- File "/usr/lib/python3/dist-packages/DistUpgrade/DistUpgradeFetcherCore.py", line 104, in authenticate
- if self.gpgauthenticate(f, sig):
- ~~~~~~~~~~~~~~~~~~~~^^^^^^^^
- File "/usr/lib/python3/dist-packages/DistUpgrade/DistUpgradeFetcherCore.py", line 119, in gpgauthenticate
- ret = subprocess.call(gpg, stderr=subprocess.PIPE)
- File "/usr/lib/python3.13/subprocess.py", line 395, in call
- with Popen(*popenargs, **kwargs) as p:
- ~~~~~^^^^^^^^^^^^^^^^^^^^^^
- File "/usr/lib/python3.13/subprocess.py", line 1039, in __init__
- self._execute_child(args, executable, preexec_fn, close_fds,
- ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- pass_fds, cwd, env,
- ^^^^^^^^^^^^^^^^^^^
- ...<5 lines>...
- gid, gids, uid, umask,
- ^^^^^^^^^^^^^^^^^^^^^^
- start_new_session, process_group)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "/usr/lib/python3.13/subprocess.py", line 1969, in _execute_child
- raise child_exception_type(errno_num, err_msg, err_filename)
+ File "/usr/bin/do-release-upgrade", line 229, in <module>
+ fetcher.run()
+ ~~~~~~~~~~~^^
+ File "/usr/lib/python3/dist-packages/DistUpgrade/DistUpgradeFetcherCore.py", line 215, in run
+ if not self.authenticate():
+ ~~~~~~~~~~~~~~~~~^^
+ File "/usr/lib/python3/dist-packages/DistUpgrade/DistUpgradeFetcherCore.py", line 104, in authenticate
+ if self.gpgauthenticate(f, sig):
+ ~~~~~~~~~~~~~~~~~~~~^^^^^^^^
+ File "/usr/lib/python3/dist-packages/DistUpgrade/DistUpgradeFetcherCore.py", line 119, in gpgauthenticate
+ ret = subprocess.call(gpg, stderr=subprocess.PIPE)
+ File "/usr/lib/python3.13/subprocess.py", line 395, in call
+ with Popen(*popenargs, **kwargs) as p:
+ ~~~~~^^^^^^^^^^^^^^^^^^^^^^
+ File "/usr/lib/python3.13/subprocess.py", line 1039, in __init__
+ self._execute_child(args, executable, preexec_fn, close_fds,
+ ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ pass_fds, cwd, env,
+ ^^^^^^^^^^^^^^^^^^^
+ ...<5 lines>...
+ gid, gids, uid, umask,
+ ^^^^^^^^^^^^^^^^^^^^^^
+ start_new_session, process_group)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ File "/usr/lib/python3.13/subprocess.py", line 1969, in _execute_child
+ raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'gpg'
```
-
- Working around that is as simple as installing `gnupg` alongside `ubuntu-release-upgrader-core`, and for that reason, the bug usually doesn't happen on less basic installation.
+ Working around that is as simple as installing `gnupg` alongside
+ `ubuntu-release-upgrader-core`, and for that reason, the bug usually
+ doesn't happen on less basic installation.
--
You received this bug notification because you are a member of Ubuntu
Foundations Bugs, which is subscribed to ubuntu-release-upgrader in
Ubuntu.
https://bugs.launchpad.net/bugs/2125687
Title:
Fail to upgrade from plucky to questing in a basic Ubuntu
Status in ubuntu-release-upgrader package in Ubuntu:
Fix Released
Status in ubuntu-release-upgrader source package in Plucky:
Won't Fix
Status in ubuntu-release-upgrader source package in Questing:
In Progress
Status in ubuntu-release-upgrader source package in Resolute:
Fix Released
Bug description:
[ Impact ]
* Users of minimal cloud images fail to run do-release-upgrade,
during the gpg validation, at the start of the tool.
The error can be worked around by manually installing gpg.
* The dependencies of u-r-u includes gpgv.
This replaces call point to gpgv instead of the possibly missing gpg command.
[ Test Plan ]
* lxc launch ubuntu-minimal:questing test
* lxc exec test -- do-release-upgrade -d
* follow interactive prompts
[ Where problems could occur ]
* The GPG validation is done at the start of the tool. If call to gpgv
was to fail, it would happen before a release upgrade starts and likely
show up as a stack trace. Although unsettling, to the user, no harm should
have been done yet.
* It is considered that gpgv, which is already set as a dependency, is a valid
drop-in replacement for calling gpg --verify in this context. In the
negative, validation of the upgrade tool integrity might be at risk.
[ Other Info ]
* The patch is already merged to resolute, but has seen only minimal testing
considering resolute doesn't have a release to upgrade to.
[ Original Description ]
Reproducer is very straightforward:
```
podman run -it ubuntu:plucky sh -c "apt update && apt upgrade -y && apt install -y ubuntu-release-upgrader-core && do-release-upgrade -d"
```
This is an interactive session, so make sure to provide answers.
Just when confirming the upgrade, the tool instantly crashes, complaining about a missing `gpg`:
```
Continue [yN] y
Get:1 Upgrade tool signature [833 B]
Get:2 Upgrade tool [966 kB]
Fetched 967 kB in 0s (0 B/s)
/usr/lib/python3/dist-packages/DistUpgrade/DistUpgradeFetcherCore.py:180: Warning: W:Download is performed unsandboxed as root as file 'questing.tar.gz.gpg' couldn't be accessed by user '_apt'. - pkgAcquire::Run (13: Permission denied)
result = fetcher.run()
authenticate 'questing.tar.gz' against 'questing.tar.gz.gpg'
Traceback (most recent call last):
File "/usr/bin/do-release-upgrade", line 229, in <module>
fetcher.run()
~~~~~~~~~~~^^
File "/usr/lib/python3/dist-packages/DistUpgrade/DistUpgradeFetcherCore.py", line 215, in run
if not self.authenticate():
~~~~~~~~~~~~~~~~~^^
File "/usr/lib/python3/dist-packages/DistUpgrade/DistUpgradeFetcherCore.py", line 104, in authenticate
if self.gpgauthenticate(f, sig):
~~~~~~~~~~~~~~~~~~~~^^^^^^^^
File "/usr/lib/python3/dist-packages/DistUpgrade/DistUpgradeFetcherCore.py", line 119, in gpgauthenticate
ret = subprocess.call(gpg, stderr=subprocess.PIPE)
File "/usr/lib/python3.13/subprocess.py", line 395, in call
with Popen(*popenargs, **kwargs) as p:
~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.13/subprocess.py", line 1039, in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pass_fds, cwd, env,
^^^^^^^^^^^^^^^^^^^
...<5 lines>...
gid, gids, uid, umask,
^^^^^^^^^^^^^^^^^^^^^^
start_new_session, process_group)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.13/subprocess.py", line 1969, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'gpg'
```
Working around that is as simple as installing `gnupg` alongside
`ubuntu-release-upgrader-core`, and for that reason, the bug usually
doesn't happen on less basic installation.
To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/ubuntu-release-upgrader/+bug/2125687/+subscriptions
More information about the foundations-bugs
mailing list