pytest-dev/pytest · error · ValueError
option dest {dest!r} already used by {option.names()!r} (thi
Error message
option dest {dest!r} already used by {option.names()!r} (this is the option that maps to dest {dest!r}); pass dest={dest!r} explicitly to share the destination What it means
Raised by OptionGroup.addoption() when two different option registrations auto-derive the same argparse destination (dest) but neither passed an explicit dest=. argparse derives dest from option names (e.g. --my-flag -> my_flag); collisions mean later options silently overwrite earlier ones, so pytest rejects this and asks for an explicit dest= to share or differentiate.
Source
Thrown at src/_pytest/config/argparsing.py:464
:param opts:
Option names, can be short or long options.
Note that lower-case short options (e.g. `-x`) are reserved.
:param attrs:
Same attributes as the argparse library's :meth:`add_argument()
<argparse.ArgumentParser.add_argument>` function accepts.
"""
conflict = set(opts).intersection(
name for opt in self.options for name in opt.names()
)
if conflict:
raise ValueError(f"option names {conflict} already added")
if self.parser and "dest" not in attrs:
dest = _get_argparse_dest(opts)
for group in self.parser._groups:
for option in group.options:
if option.dest == dest:
raise ValueError(
f"option dest {dest!r} already used by "
f"{option.names()!r} (this is the option that maps to "
f"dest {dest!r}); pass dest={dest!r} explicitly "
"to share the destination"
)
self._addoption_inner(opts, attrs, allow_reserved=False)
def _addoption(self, *opts: str, **attrs: Any) -> None:
"""Like addoption(), but also allows registering short lower case options (e.g. -x),
which are reserved for pytest core."""
self._addoption_inner(opts, attrs, allow_reserved=True)
def _addoption_inner(
self, opts: tuple[str, ...], attrs: dict[str, Any], allow_reserved: bool
) -> None:
if not allow_reserved:
for opt in opts:
if len(opt) >= 2 and opt[0] == "-" and opt[1].islower():View on GitHub (pinned to 98b357f69e)
Solutions
- If the two options should share storage, pass dest='shared_name' explicitly to both.
- If they should be separate, rename one option so its derived dest differs.
- Remove the redundant option entirely if it was a duplicate.
Example fix
# before
group.addoption('--my-flag')
group.addoption('--myflag') # same dest 'my_flag'
# after (share explicitly)
group.addoption('--my-flag', dest='my_flag')
group.addoption('--myflag', dest='my_flag') Defensive patterns
Strategy: validation
Validate before calling
def derived_dest(*opts: str) -> str:
# mirror argparse dest derivation
long = [o for o in opts if o.startswith('--')]
name = (long[0] if long else opts[0]).lstrip('-')
return name.replace('-', '_')
# before addoption, check no prior option shares this dest, or pass dest= explicitly Prevention
- Pass dest= explicitly whenever option names could normalize to the same destination.
- Avoid registering both hyphenated and underscored variants of the same option.
- Audit option dests when refactoring CLI option names.
When it happens
Trigger: Registering '--my-flag' and '--myflag' separately: both derive dest 'my_flag'. Or '--foo-bar' after '--foo_bar' already exists. The loop at line 459-469 finds a prior option with the same computed dest.
Common situations: Adding a hyphenated and an underscored variant of the same logical option; two plugins choosing names that normalize to the same dest; refactoring option names without checking dest collisions.
Related errors
- option names {conflict} already added
- lowercase short options are reserved
- {optname} must be a filename, given: {path}
- {optname} must be a directory, given: {path}
- while parsing the following warning configuration: {arg}
AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04).
Data as JSON: /data/errors/2e6bc1a2ef55f95c.json.
Report an issue: GitHub.