Argparse ValueError: action store_true is not valid for positional arguments

After upgrading to Python 3.14, my argparse code raises the following error:

ValueError: action ‘store_true‘ is not valid for positional arguments

$ basketcase -h
Traceback (most recent call last):
  File "/home/dsilva/.local/share/virtualenvs/basketcase--xOC7pu1/bin/basketcase", line 7, in <module>
    sys.exit(main())
             ~~~~^^
  File "/home/dsilva/Code/basketcase/src/basketcase/__main__.py", line 305, in main
    session_list_parser.add_argument(
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
        'list',
        ^^^^^^^
        help='Print a list of available sessions',
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        action='store_true'
        ^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/usr/lib64/python3.14/argparse.py", line 1540, in add_argument
    raise ValueError(f'action {action_name!r} is not valid for positional arguments')
ValueError: action 'store_true' is not valid for positional arguments

This is a program called basketcase. The complete argparse code is published here.

It starts by defining a top-level subparser.

    commands = parser.add_subparsers(
        title='commands', required=True
    )

Then it adds a sub-command session.

    # session subparser
    session_parser = commands.add_parser(
        'session',
        help='Session management command help'
    )

    session_commands = session_parser.add_subparsers(
        title='Commands', required=True
    )

And then it adds a sub-command of session called list. You would run it as basketcase session list.

    # session sub-command parsers
    session_list_parser = session_commands.add_parser(
        'list',
        help='Print a list of available sessions'
    )

    session_list_parser.set_defaults(action=_session_list)

    session_list_parser.add_argument(
        'list',
        help='Print a list of available sessions',
        action='store_true'
    )

Apparently, it no longer allows using store_true for positional arguments, but I couldn’t figure out why.

list is not an optional argument; and, as far as I know, we’re not supposed to use “required options” for this. What am I supposed to use, then?

This was a deliberate change from python/cpython#124839 - see python/cpython#85935 and python/cpython#97848 for the rational.

As mentioned in this comment, you can try passing dest to add_subparsers() to store the name of the subcommand that was used.

Thanks for finding that. They totally forgot to add this very important change to the release notes.


It turns out that I don’t need to use dest, because I already use set_defaults to call a function, depending on the subparser used.

    # session sub-command parsers
    session_list_parser = session_commands.add_parser(
        'list',
        help='Print a list of available sessions'
    )

    session_list_parser.set_defaults(action=_session_list)

-    session_list_parser.add_argument(
-        'list',
-        help='Print a list of available sessions',
-        action='store_true'
-    )

In other words, I just had to delete the add_argument call. It was redundant anyway and I didn’t realize that until now.