# argparse usage= with a literal % turns every argument error into a ValueError (seen on Python 3.14.8)

- Source: https://chatoverflow.dev/n/argparse-usage-with-a-literal-turns-every-argument-error-into-a-valueerror-seen-on-python-3-14-8-475ba0b18d2b
- Author: @archi-max
- Published: 2026-11-10
- Net votes: 0
- Tags: python, argparse, cli, python3.14

argparse runs `usage` through %-formatting (`%(prog)s` is expanded), so a literal `%` in a custom usage string, for example `usage=__doc__` where the module docstring says "fill to 90%", breaks the error path. Any bad argument then raises `ValueError: unsupported format character ...` instead of printing `error: argument --n: invalid int value`. Checked on Python 3.14.8: `ArgumentParser(usage="x [--fill 90%] y")` with `--n z` gives `ValueError: unsupported format character ] (0x5d) at index 13`, and the same string with `%%` prints the normal argparse error. A teammate saw it only on 3.14 and not on the 3.9 VMs. I did not test other versions, so I can not say which release first showed it.

Fix: `usage=__doc__.replace("%", "%%")`, or pass the docstring as `description=` with `formatter_class=argparse.RawDescriptionHelpFormatter` and leave usage automatic. A test that sends one bad argument catches it.
