{"id":"dc72fa8f91e88a1c","repo":"pytest-dev/pytest","slug":"option-names-conflict-already-added","errorCode":null,"errorMessage":"option names {conflict} already added","messagePattern":"option names (.+?) already added","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/_pytest/config/argparsing.py","lineNumber":457,"sourceCode":"        \"\"\"Add an option to this group.\n\n        If a shortened version of a long option is specified, it will\n        be suppressed in the help. ``addoption('--twowords', '--two-words')``\n        results in help showing ``--two-words`` only, but ``--twowords`` gets\n        accepted **and** the automatic destination is in ``args.twowords``.\n\n        :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)","sourceCodeStart":439,"sourceCodeEnd":475,"githubUrl":"https://github.com/pytest-dev/pytest/blob/98b357f69e380da908740a212288d73b2ee06687/src/_pytest/config/argparsing.py#L439-L475","documentation":"Raised by OptionGroup.addoption() when one or more of the supplied option strings (e.g. '--flag') have already been registered by a previous addoption call in the same parser. pytest rejects duplicate option names to prevent ambiguous command-line parsing.","triggerScenarios":"Two addoption calls registering the same '--myflag', or a plugin re-registering an option that pytest core or another plugin already added. The set intersection at line 453-455 finds the conflict.","commonSituations":"Loading two plugins that both define the same option; a conftest.py adding an option that a plugin also adds; upgrading a plugin that newly defines an option your conftest already defines.","solutions":["Remove the duplicate addoption from your conftest or plugin.","Guard registration with a check like `if not parser.getoption('--myflag', default=None)`.","Rename your custom option to a plugin-namespaced form (e.g. '--myplugin-flag').","Disable the conflicting plugin via -p no:pluginname."],"exampleFix":"# before\ndef pytest_addoption(parser):\n    parser.addoption('--foo', ...)\n    parser.addoption('--foo', ...)  # duplicate\n\n# after\ndef pytest_addoption(parser):\n    parser.addoption('--foo', ...)\n    parser.addoption('--plugin-foo', ...)","handlingStrategy":"validation","validationCode":"def option_already_registered(existing: list, *opts: str) -> bool:\n    names = {n for opt in existing for n in opt}\n    return bool(set(opts) & names)","typeGuard":null,"tryCatchPattern":"try:\n    group.addoption('--myflag', ...)\nexcept ValueError as e:\n    if 'already added' in str(e):\n        pass  # already registered by another plugin; skip","preventionTips":["Guard addoption with a check that the option isn't already present.","Namespace custom CLI options to avoid cross-plugin clashes.","Use -p no:plugin to disable conflicting plugins when debugging."],"tags":["pytest","plugin","config","addoption","naming-conflict","cli"],"analyzedSha":"98b357f69e380da908740a212288d73b2ee06687","analyzedAt":"2026-08-04T20:26:34.442Z","schemaVersion":2}