pytest-dev/pytest · error · ValueError

is already an alias of

Error message

{alias!r} is already an alias of {already!r}

What it means

Raised during addini() when an alias in the aliases= list was already registered as an alias of another option. Each alias string can map to only one canonical option. The check `(already := self._ini_aliases.get(alias)) is not None` finds a prior mapping.

Solutions

  1. Use a unique alias not already claimed by another option
  2. Remove the duplicate alias from the earlier addini call if it is no longer needed
  3. Inspect self._ini_aliases before registering to find available aliases

Example fix

# before
parser.addini('opt_a', type='string', aliases=['shared'])
parser.addini('opt_b', type='string', aliases=['shared'])

# after
parser.addini('opt_a', type='string', aliases=['shared'])
parser.addini('opt_b', type='string', aliases=['shared_b'])
Defensive patterns

Strategy: validation

Validate before calling

def check_alias_not_taken(parser, aliases: list[str]) -> dict[str, str]:
    taken = {a: parser._ini_aliases[a] for a in aliases if a in parser._ini_aliases}
    return taken
# Usage: taken = check_alias_not_taken(parser, ['shared'])

Prevention

When it happens

Trigger: Calling parser.addini('opt_b', aliases=['shared']) when 'shared' was already used as an alias for 'opt_a' in a prior addini call. The alias key already exists in self._ini_aliases.

Common situations: Two plugins independently choosing the same alias string. Refactoring and forgetting an old alias registration. Copy-pasting addini calls with shared alias values.

Related errors


AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11). Data as JSON: /api/errors/ef293d4e028b19a3. Report an issue: GitHub.

Appendix: source

Thrown at src/_pytest/config/argparsing.py:364

            ini_type = _ini_type_to_member(name, type)
        if default is NOTSET:
            if isinstance(ini_type, (tuple, _IniLiteral)):
                kind = "union" if isinstance(ini_type, tuple) else "Literal"
                raise ValueError(
                    f"ini option {name!r} has a {kind} type, which has no "
                    "implicit default; pass an explicit `default` to `addini`"
                )
            default = get_ini_default_for_type(ini_type)

        self._inidict[name] = (help, ini_type, default)

        for alias in aliases:
            if alias in self._inidict:
                raise ValueError(
                    f"alias {alias!r} conflicts with existing configuration option"
                )
            if (already := self._ini_aliases.get(alias)) is not None:
                raise ValueError(f"{alias!r} is already an alias of {already!r}")
            self._ini_aliases[alias] = name


def get_ini_default_for_type(type: _IniTypeTag) -> Any:
    """
    Used by addini to get the default value for a given config option type, when
    default is not supplied.
    """
    if type in ("paths", "pathlist", "args", "linelist"):
        return []
    elif type == "bool":
        return False
    elif type == "int":
        return 0
    elif type == "float":
        return 0.0
    else:
        return ""

View on GitHub (pinned to 0d6fbdeffa)