#1140927 depthcharge-tools: Traceback with 3.14: args for positionals must be != 0

#1140927#5
Date:
2026-06-28 13:35:38 UTC
From:
To:
Package: depthcharge-tools
Version: 0.6.2-4
Severity: serious
Tags: d-i
Justification: working depthchargectl invokations break all of a sudden, breaks d-i
X-Debbugs-Cc: debian-boot@lists.debian.org, debian-kernel@lists.debian.org, reproducible-builds@lists.alioth.debian.org

Hi,

The python3-defaults package was just switched from 3.13 to 3.14 and
that breaks debian-installer builds. Previously, that's been working
fine for a very long time:

    update-manifest dest/cdrom/gtk/debian-cd_info.tar.gz "isolinux help screens for CD (graphical)"
    pigz -nm -v -d <tmp/cdrom_gtk/initrd.gz |   xz -T0 --check=crc32 --block-size=1M -v >tmp/cdrom_gtk/initrd.xz
    <stdin> to <stdout>
    (stdin): 57.1 MiB / 134.4 MiB = 0.425, 14 MiB/s, 0:09
    rm -f ./tmp/cdrom_gtk/depthcharge/*
    mkdir -p ./tmp/cdrom_gtk/depthcharge
    for board in amd64-generic; do \
            depthchargectl build -v \
                    --board ${board} \                                                                            
                    --kernel-release 7.0.13+deb14-amd64 \                                                         
                    --kernel ./tmp/cdrom_gtk/vmlinuz \                                                            
                    --initramfs ./tmp/cdrom_gtk/initrd.xz \                                                       
                    --root none \                                                                                 
                    --kernel-cmdline "partman-partitioning/default_label=gpt --- quiet" \                         
                    --output ./tmp/cdrom_gtk/depthcharge/${board}.kernel.img; \                                   
            gen-hd-image -v -z \
                    -X gpt \
                    -p $(($(stat -c%s ./tmp/cdrom_gtk/depthcharge/${board}.kernel.img) / 512 + 2048)) \
                    -i $(mktemp -d) \
                    -o ./tmp/cdrom_gtk/depthcharge/${board}.disk.img \
                    -d FE3A2A5D-4F32-41A7-B725-ACCC3285A309 \
                    ./tmp/cdrom_gtk/depthcharge/${board}.kernel.img \
                    2048; \
            pigz -9nmf ./tmp/cdrom_gtk/depthcharge/${board}.kernel.img; \
    done
    Couldn't find /boot in fstab, falling back to '/boot'.
    Assuming board 'Unnamed amd64-generic board' ('amd64-generic') by codename argument or config.
    Using kernel cmdline from given options: partman-partitioning/default_label=gpt --- quiet
    Building depthcharge image for board 'Unnamed amd64-generic board' ('amd64-generic').
    Building for kernel version '7.0.13+deb14-amd64'.
    Trying with compression 'none'.
    Using file '/build/reproducible-path/debian-installer-20250804/build/tmp/cdrom_gtk/vmlinuz' as a vmlinuz.
    Trying to decompress file '/build/reproducible-path/debian-installer-20250804/build/tmp/cdrom_gtk/vmlinuz'.
    Using file '/build/reproducible-path/debian-installer-20250804/build/tmp/cdrom_gtk/initrd.xz' as an initramfs.
    Using keyblock file '/usr/share/vboot/devkeys/kernel.keyblock'.
    Using signprivate file '/usr/share/vboot/devkeys/kernel_data_key.vbprivk'.
    Using signpubkey file '/usr/share/vboot/devkeys/kernel_subkey.vbpubk'.
    Vmlinuz pref_address is 0x1000000, with init_size 0x3c47000.
    Padding vmlinuz to size 0xdaa000
    Packing files as temporary image.
    […]

That broke all of a sudden with a traceback:

    update-manifest dest/cdrom/gtk/debian-cd_info.tar.gz "isolinux help screens for CD (graphical)"
    pigz -nm -v -d <tmp/cdrom_gtk/initrd.gz |   xz -T0 --check=crc32 --block-size=1M -v >tmp/cdrom_gtk/initrd.xz
    <stdin> to <stdout>
    (stdin): 57.1 MiB / 134.4 MiB = 0.425, 14 MiB/s, 0:09
    rm -f ./tmp/cdrom_gtk/depthcharge/*
    mkdir -p ./tmp/cdrom_gtk/depthcharge
    for board in amd64-generic; do \
            depthchargectl build -v \
                    --board ${board} \                                                                           
                    --kernel-release 7.0.13+deb14-amd64 \                                                        
                    --kernel ./tmp/cdrom_gtk/vmlinuz \                                                           
                    --initramfs ./tmp/cdrom_gtk/initrd.xz \                                                      
                    --root none \                                                                                
                    --kernel-cmdline "partman-partitioning/default_label=gpt --- quiet" \                        
                    --output ./tmp/cdrom_gtk/depthcharge/${board}.kernel.img; \                                  
            gen-hd-image -v -z \
                    -X gpt \
                    -p $(($(stat -c%s ./tmp/cdrom_gtk/depthcharge/${board}.kernel.img) / 512 + 2048)) \
                    -i $(mktemp -d) \
                    -o ./tmp/cdrom_gtk/depthcharge/${board}.disk.img \
                    -d FE3A2A5D-4F32-41A7-B725-ACCC3285A309 \
                    ./tmp/cdrom_gtk/depthcharge/${board}.kernel.img \
                    2048; \
            pigz -9nmf ./tmp/cdrom_gtk/depthcharge/${board}.kernel.img; \
    done
 →  Traceback (most recent call last):
 →    file "/usr/bin/depthchargectl", line 33, in <module>
 →      sys.exit(load_entry_point('depthcharge-tools==0.6.2', 'console_scripts', 'depthchargectl')())
 →               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
 →    File "/usr/lib/python3/dist-packages/depthcharge_tools/utils/argparse.py", line 895, in main
 →      parser = cls.parser
 →               ^^^^^^^^^^
 →    File "/usr/lib/python3/dist-packages/depthcharge_tools/utils/argparse.py", line 1042, in parser
 →      return cls.__build()
 →             ~~~~~~~~~~~^^
 →    File "/usr/lib/python3/dist-packages/depthcharge_tools/utils/argparse.py", line 1065, in __build
 →      arg.build(parser)
 →      ~~~~~~~~~^^^^^^^^
 →    File "/usr/lib/python3/dist-packages/depthcharge_tools/utils/argparse.py", line 439, in build
 →      return parent.add_argument(*option_strings, **kwargs)
 →             ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
 →    File "/usr/lib/python3.14/argparse.py", line 1531, in add_argument
 →      kwargs = self._get_positional_kwargs(*args, **kwargs)
 →    File "/usr/lib/python3.14/argparse.py", line 1666, in _get_positional_kwargs
 →      raise ValueError('nargs for positionals must be != 0')
 →  ValueError: nargs for positionals must be != 0
    stat: cannot statx './tmp/cdrom_gtk/depthcharge/amd64-generic.kernel.img': No such file or directory
    /bin/sh: 10: arithmetic expression: expecting primary: " / 512 + 2048"
    make[4]: *** [config/x86.cfg:437: arch_depthcharge] Error 2
    make[3]: *** [Makefile:315: _build] Error 2
    make[2]: *** [Makefile:309: build_cdrom_gtk] Error 2
    make[1]: *** [Makefile:315: _build] Error 2
    make: *** [Makefile:309: build_cdrom_isolinux] Error 2

(The parts after the traceback can be ignored, that's definitely a
problem in the installer's Makefile.)

I didn't immediately spot a breaking change in the “what's new in 3.14”
page, or the argparse documentation, but a quick search in CPython's git
repository quickly returned the following:

    commit 9944ad388c457325456152257b977410c4ec3593
    Author: Serhiy Storchaka <storchaka@gmail.com>
    Date:   Sat Oct 12 16:04:17 2024 +0300

        gh-85935: Check for nargs=0 for positional arguments in argparse (GH-124839)

        Raise ValueError in add_argument() if either explicit nargs=0 or action
        that does not consume arguments (like 'store_const' or 'store_true') is
        specified for positional argument.

    diff --git a/Lib/argparse.py b/Lib/argparse.py
    index cbecb3b753c..550415dc934 100644
    --- a/Lib/argparse.py
    +++ b/Lib/argparse.py
    @@ -1441,11 +1441,17 @@ def add_argument(self, *args, **kwargs):
                     kwargs['default'] = self.argument_default

             # create the action object, and add it to the parser
    +        action_name = kwargs.get('action')
             action_class = self._pop_action_class(kwargs)
             if not callable(action_class):
                 raise ValueError('unknown action "%s"' % (action_class,))
             action = action_class(**kwargs)

    +        # raise an error if action for positional argument does not
    +        # consume arguments
    +        if not action.option_strings and action.nargs == 0:
    +            raise ValueError(f'action {action_name!r} is not valid for positional arguments')
    +
             # raise an error if the action type is not callable
             type_func = self._registry_get('type', action.type, action.type)
             if not callable(type_func):
    @@ -1554,7 +1560,9 @@ def _get_positional_kwargs(self, dest, **kwargs):
             # mark positional arguments as required if at least one is
             # always required
             nargs = kwargs.get('nargs')
    -        if nargs not in [OPTIONAL, ZERO_OR_MORE, REMAINDER, SUPPRESS, 0]:
    +        if nargs == 0:
    +            raise ValueError('nargs for positionals must be != 0')
    +        if nargs not in [OPTIONAL, ZERO_OR_MORE, REMAINDER, SUPPRESS]:
                 kwargs['required'] = True

             # return the keyword arguments with no option strings

And that's be consistent with the 3.13 versus 3.14 hypothesis:

    kibi@tokyo:~/hack/cpython.git (main =)$ git describe --contains --tags 9944ad388c457325456152257b977410c4ec3593
    v3.14.0a1~62


Cheers,

#1140927#10
Date:
2026-06-28 14:47:07 UTC
From:
To:
Adrian Bunk <bunk@debian.org> (2026-06-28):

Thanks, Adrian.

Merging this patch into a +kibi1 version of the depthcharge-tools
package makes debian-installer buildable again. I'm not sure I want to
take the responsibility of uploading this in a rush though, given (1)
the lack of upstream feedback and (2) the fact both current code and fix
are said to be hackish.

Looping in depthcharge-tools@ explicitly, it'd be great to have some
guidance here.


Cheers,

#1140927#13
Date:
2026-06-28 16:21:00 UTC
From:
To:
Hello,

Bug #1140927 in depthcharge-tools reported by you has been fixed in the
Git repository and is awaiting an upload. You can see the commit
message below and you can check the diff of the fix at:

https://salsa.debian.org/python-team/packages/depthcharge-tools/-/commit/bf99eb9cb7be797be53e8322cc6c00c7c657cb00
------------------------------------------------------------------------
utils: argparse: suppress some arguments from Python argparse

Closes: #1140927
------------------------------------------------------------------------

(this message was generated automatically)
-- 
Greetings

https://bugs.debian.org/1140927

#1140927#20
Date:
2026-06-28 16:44:35 UTC
From:
To:
We believe that the bug you reported is fixed in the latest version of
depthcharge-tools, which is due to be installed in the Debian FTP archive.

A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to 1140927@bugs.debian.org,
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Colin Watson <cjwatson@debian.org> (supplier of updated depthcharge-tools package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing ftpmaster@ftp-master.debian.org)
Format: 1.8
Date: Sun, 28 Jun 2026 17:20:33 +0100
Source: depthcharge-tools
Architecture: source
Version: 0.6.2-5
Distribution: unstable
Urgency: medium
Maintainer: Debian Python Team <team+python@tracker.debian.org>
Changed-By: Colin Watson <cjwatson@debian.org>
Closes: 1140927
Changes:
 depthcharge-tools (0.6.2-5) unstable; urgency=medium
 .
   * Team upload.
   * utils: argparse: suppress some arguments from Python argparse (closes:
     #1140927).
   * Add a superficial autopkgtest for `depthchargectl --help`.
Checksums-Sha1:
 ab53eb19a28b2cda942c1bc3ec2042d7c9da3aa6 2464 depthcharge-tools_0.6.2-5.dsc
 a83c80bcf2be94c2793ec864484e36b891b8740a 8080 depthcharge-tools_0.6.2-5.debian.tar.xz
 76b5b61458a26952bccf49f6e1ba2146530a49a5 260348 depthcharge-tools_0.6.2-5.git.tar.xz
 280a51077beee79bf5052d4a4d78085ccc622aeb 17536 depthcharge-tools_0.6.2-5_source.buildinfo
Checksums-Sha256:
 a4c70a9b3f26b01eb945ed5792e23b31b39cca8e90fe08d162fe2a9a427cc7f4 2464 depthcharge-tools_0.6.2-5.dsc
 6427356fa3a2c5dd3bcfc705cd59f20baa46b7f5c9441ed8317dc7ad7a8cf632 8080 depthcharge-tools_0.6.2-5.debian.tar.xz
 d4e9eb6a4c17c23bee9e55f5fc26c6a31f80cdcb5468b96cbfb0a3ff6f2ff85b 260348 depthcharge-tools_0.6.2-5.git.tar.xz
 1e3e7e1a052ee1d1a717bc4890df03b3a10c10c98808a200c21a02239830b6c3 17536 depthcharge-tools_0.6.2-5_source.buildinfo
Files:
 f7ef548874f77c4cfe4ff59830b3a01b 2464 admin optional depthcharge-tools_0.6.2-5.dsc
 1fde307b8e0864d1b91a49060dd5b191 8080 admin optional depthcharge-tools_0.6.2-5.debian.tar.xz
 b1fdca3f04c8b447754536dea85c79d8 260348 admin optional depthcharge-tools_0.6.2-5.git.tar.xz
 729004f17b2b3b999dbc78ccc8e7b279 17536 admin optional depthcharge-tools_0.6.2-5_source.buildinfo
Git-Tag-Info: tag=b046c9d62310460af4d14f04477835017736c53a fp=ac0a4ff12611b6fccf01c111393587d97d86500b
Git-Tag-Tagger: Colin Watson <cjwatson@debian.org>
-----BEGIN PGP SIGNATURE-----

iQIzBAEBCgAdFiEEN02M5NuW6cvUwJcqYG0ITkaDwHkFAmpBSikACgkQYG0ITkaD
wHninQ/8DCOoVd8VdwtJuS21UyAhYJfZrkbNy9+ou1IQv2WtywFRZIgKFodIzYUK
ti5ZYEa9P32QufZhXQ/vP2O0BjUlsF5Pdu6/uCfg7yuB8863UjqZKUpRZFvNECWN
eKnPcnI8TT7vYW2o4T3xpoZdJq5xxrnV6YJjdCrdI7jO1iceQDaLLqJgRpAOvwBy
Rr8ZgyOZdY5SFsnYp5MDyVZqtbwk95AnkjRsbbXeKTfMz2fWMEiC2dja40O7oJxk
jx9BiwN8rmZFonS7zvqN/uadingPD51H4f2cxbAHxrVKX5YtdqJGXKmFP4xRI1YU
YIHgBXHeOLmw3+MmBlXR25e1kDFsa/U3hCURE2q2TNRX5ZbjmMdBYxkbIZpmDi73
JabWllix/6ByhRPoovDvLKbYQgmpPF3g1amcpWDYSXUdtRotbhEqyZEzoSTMdEIx
6mU4u3rP+Jy7hFXkvdRlX3jo0c1vuUiQenlWbCCvnqpyzN+zSTVxmfz/tlOYYRED
DzdH+TiMxuMQPk8t2gq4vG9+OFVEqPrLRkvYGgSEGLW58iWKJwBGEIPhZYUT8lqi
TzKXsMhp9HReLiWUuzuIiZ4rerM8pmoInZVp5pMdIZU8p72omLBrbG5oZ6lT1vJz
AFudqLmUVEbMb/dEgN0c6ELsOn4bat/e3Oh2/tNApkAUonfeEL8=
=bhiM
-----END PGP SIGNATURE-----