{"record":{"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/0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc/src/_pytest/config/argparsing.py#L446-L482","documentation":"Raised by pytest's option parser when a plugin or conftest calls group.addoption() with an option whose argparse-generated destination (dest) collides with another already-registered option. Because the destination is auto-derived from the option strings (e.g. --foo-bar => foo_bar), two differently-named options can map to the same dest. pytest refuses the ambiguity rather than silently overwriting.","triggerScenarios":"Calling group.addoption('--foo-bar') after '--foo_bar' was already added (both yield dest 'foo_bar'); or registering '--foo' in two groups where argparse's internal dest dedup kicks in. The check runs only when 'dest' is not explicitly set in attrs and the group is attached to a parser.","commonSituations":"Two plugins registering options with names that normalize to the same dest (hyphens vs underscores); upgrading a plugin that now adds an option colliding with your conftest.py custom option; copy-pasting an addoption across conftest files.","solutions":["Pass an explicit dest=... to addoption() so the two options intentionally share (or differentiate) the destination: group.addoption('--foo-bar', dest='foo_bar').","Rename one of the colliding option strings so they no longer map to the same dest.","Audit conftest.py and installed plugins (pytest --trace-config) for the option names reported in the message and remove the duplicate."],"exampleFix":"// before\ngroup.addoption('--foo-bar')\ngroup.addoption('--foo_bar')\n// after\ngroup.addoption('--foo-bar')\ngroup.addoption('--foo_bar', dest='foo_bar_alt')","handlingStrategy":"validation","validationCode":"from argparse import Namespace\n\ndef safe_addoption(group, *opts, **attrs):\n    from _pytest.config.argparsing import _get_argparse_dest\n    if 'dest' not in attrs and group.parser:\n        dest = _get_argparse_dest(opts)\n        for g in group.parser._groups:\n            for o in g.options:\n                if o.dest == dest:\n                    raise SystemExit(f'pre-conflict: dest {dest!r} used by {o.names()!r}')\n    group.addoption(*opts, **attrs)","typeGuard":"null","tryCatchPattern":"null","preventionTips":["Always pass dest=... explicitly when registering options in plugins to make destinations unambiguous.","Run pytest --trace-config after registering options to spot duplicates early.","Namespace your plugin options with a prefix to avoid accidental dest collisions."],"tags":["config","argparse","plugins","conftest"],"backgroundTag":null,"analyzedSha":"0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc","analyzedAt":"2026-08-11T20:52:36.969Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}