{"id":"2e6bc1a2ef55f95c","repo":"pytest-dev/pytest","slug":"option-dest-dest-r-already-used-by-option-names","errorCode":null,"errorMessage":"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","messagePattern":"option dest (.+?) already used by (.+?) \\(this is the option that maps to dest (.+?)\\); pass dest=(.+?) explicitly to share the destination","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/_pytest/config/argparsing.py","lineNumber":464,"sourceCode":"        :param opts:\n            Option names, can be short or long options.\n            Note that lower-case short options (e.g. `-x`) are reserved.\n        :param attrs:\n            Same attributes as the argparse library's :meth:`add_argument()\n            <argparse.ArgumentParser.add_argument>` function accepts.\n        \"\"\"\n        conflict = set(opts).intersection(\n            name for opt in self.options for name in opt.names()\n        )\n        if conflict:\n            raise ValueError(f\"option names {conflict} already added\")\n\n        if self.parser and \"dest\" not in attrs:\n            dest = _get_argparse_dest(opts)\n            for group in self.parser._groups:\n                for option in group.options:\n                    if option.dest == dest:\n                        raise ValueError(\n                            f\"option dest {dest!r} already used by \"\n                            f\"{option.names()!r} (this is the option that maps to \"\n                            f\"dest {dest!r}); pass dest={dest!r} explicitly \"\n                            \"to share the destination\"\n                        )\n        self._addoption_inner(opts, attrs, allow_reserved=False)\n\n    def _addoption(self, *opts: str, **attrs: Any) -> None:\n        \"\"\"Like addoption(), but also allows registering short lower case options (e.g. -x),\n        which are reserved for pytest core.\"\"\"\n        self._addoption_inner(opts, attrs, allow_reserved=True)\n\n    def _addoption_inner(\n        self, opts: tuple[str, ...], attrs: dict[str, Any], allow_reserved: bool\n    ) -> None:\n        if not allow_reserved:\n            for opt in opts:\n                if len(opt) >= 2 and opt[0] == \"-\" and opt[1].islower():","sourceCodeStart":446,"sourceCodeEnd":482,"githubUrl":"https://github.com/pytest-dev/pytest/blob/98b357f69e380da908740a212288d73b2ee06687/src/_pytest/config/argparsing.py#L446-L482","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\ngroup.addoption('--my-flag')\ngroup.addoption('--myflag')  # same dest 'my_flag'\n\n# after (share explicitly)\ngroup.addoption('--my-flag', dest='my_flag')\ngroup.addoption('--myflag', dest='my_flag')","handlingStrategy":"validation","validationCode":"def derived_dest(*opts: str) -> str:\n    # mirror argparse dest derivation\n    long = [o for o in opts if o.startswith('--')]\n    name = (long[0] if long else opts[0]).lstrip('-')\n    return name.replace('-', '_')\n# before addoption, check no prior option shares this dest, or pass dest= explicitly","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["pytest","plugin","config","addoption","argparse","dest","cli"],"analyzedSha":"98b357f69e380da908740a212288d73b2ee06687","analyzedAt":"2026-08-04T20:26:34.442Z","schemaVersion":2}