ansible/ansible · error · ValueError
internal error: required and default are mutually exclusive
Error message
internal error: required and default are mutually exclusive for %s
What it means
Raised by _handle_aliases() in ansible.module_utils.common.parameters with ValueError when an argument_spec entry declares both required=True and a non-None default. These are mutually exclusive because a required parameter must always be supplied by the user, so a default can never apply. The 'internal error' prefix signals a bug in the module's own spec, not user input.
Source
Thrown at lib/ansible/module_utils/common/parameters.py:232
:param alias_deprecations:
:type alias_deprecations: list
"""
aliases_results = {} # alias:canon
for (k, v) in argument_spec.items():
aliases = v.get('aliases', None)
default = v.get('default', None)
required = v.get('required', False)
if alias_deprecations is not None:
for alias in argument_spec[k].get('deprecated_aliases', []):
if alias.get('name') in parameters:
alias_deprecations.append(alias)
if default is not None and required:
# not alias specific but this is a good place to check this
raise ValueError("internal error: required and default are mutually exclusive for %s" % k)
if aliases is None:
continue
if not is_iterable(aliases) or isinstance(aliases, (bytes, str)):
raise TypeError('internal error: aliases must be a list or tuple')
for alias in aliases:
aliases_results[alias] = k
if alias in parameters:
if k in parameters and alias_warnings is not None:
alias_warnings.append((k, alias))
parameters[k] = parameters[alias]
return aliases_results
def _list_deprecations(argument_spec, parameters, prefix=''):View on GitHub (pinned to 9cf16a4aca)
Solutions
- Decide the semantics: if the value is truly required, remove the default
- If a sensible fallback exists, remove required: true and keep the default
- Add a unit test that instantiates the module (or validates the spec) so spec errors fail in CI, not on the target host
Example fix
# before
argument_spec = dict(
path=dict(type='str', required=True, default='/tmp'),
)
# after
argument_spec = dict(
path=dict(type='str', default='/tmp'),
) Defensive patterns
Strategy: validation
Validate before calling
for name, spec in argument_spec.items():
if spec.get('required') and spec.get('default') is not None:
raise AssertionError(f'{name}: required and default are mutually exclusive') Prevention
- Never combine required=True with a default in argument_spec
- Cover specs with unit tests / ansible-test sanity validate-modules before release
- Remember default=None with required=True is legal; only non-None defaults conflict
When it happens
Trigger: Defining argument_spec = {'name': {'required': True, 'default': 'x'}} and instantiating AnsibleModule. Note the check uses `default is not None`, so default=None with required=True is allowed.
Common situations: Module authors adding a default for convenience after previously marking a param required; copy-paste of spec entries; third-party or collection modules with untested spec combinations.
Related errors
- internal error: aliases must be a list or tuple
- {0} '{1}' is unsupported. Valid types are: {2}
- required and default are mutually exclusive for {0}
- invalid value for masklen
- invalid value for netmask: %s
AI-assisted analysis of ansible/ansible@9cf16a4aca (2026-08-15).
Data as JSON: /api/errors/0577a84b171899f4.
Report an issue: GitHub.