ansible/ansible · error · AnsibleParserError

Detected range in host but was asked to ignore ranges

Error message

Detected range in host but was asked to ignore ranges

What it means

Raised by parse_address() in lib/ansible/parsing/utils/addresses.py when the string parsed successfully as a host pattern containing one or more '[' range specifications (e.g. foo[1:3].example.com) but the caller passed allow_ranges=False. The pattern is valid, but the caller explicitly declined to accept ranges, so it is treated as a parse failure via AnsibleParserError.

Source

Thrown at lib/ansible/parsing/utils/addresses.py:212

    # What we're left with now must be an IPv4 or IPv6 address, possibly with
    # numeric ranges, or a hostname with alphanumeric ranges.

    host = None
    for matching in ['ipv4', 'ipv6', 'hostname']:
        m = patterns[matching].match(address)
        if m:
            host = address
            continue

    # If it isn't any of the above, we don't understand it.
    if not host:
        raise AnsibleError("Not a valid network hostname: %s" % address)

    # If we get to this point, we know that any included ranges are valid.
    # If the caller is prepared to handle them, all is well.
    # Otherwise we treat it as a parse failure.
    if not allow_ranges and '[' in host:
        raise AnsibleParserError("Detected range in host but was asked to ignore ranges")

    return (host, port)

View on GitHub (pinned to 9cf16a4aca)

Solutions

  1. Expand the range before parsing: use ansible.plugins.inventory.expand_hostname_range() or ansible.utils.display helpers to turn 'web[1:3]' into individual hosts, then call parse_address() on each.
  2. If you actually want a single host, remove the '[...]' range syntax and pass the literal hostname.
  3. If your code genuinely supports patterns, call parse_address(address, allow_ranges=True) and handle the range yourself.

Example fix

# before
host, port = parse_address('web[01:03]')  # raises
# after
from ansible.plugins.inventory import expand_hostname_range
for h in expand_hostname_range('web[01:03]'):
    host, port = parse_address(h)
Defensive patterns

Strategy: validation

Validate before calling

from ansible.parsing.utils.addresses import parse_address

def parse_single_host(address: str):
    # reject inventory range syntax before it reaches parse_address
    if '[' in address or ']' in address:
        raise ValueError(f'range pattern not allowed here: {address!r} — expand it first')
    return parse_address(address, allow_ranges=False)

Try / catch

from ansible.errors import AnsibleParserError, AnsibleError
from ansible.parsing.utils.addresses import parse_address
try:
    host, port = parse_address(address)
except AnsibleParserError as e:  # range in host
    hosts = expand_hostname_range(address)
    results = [parse_address(h) for h in hosts]
except AnsibleError:
    raise

Prevention

When it happens

Trigger: Calling parse_address('web[01:05]', allow_ranges=False), which is the default; any code path that needs one concrete host (e.g. connection plugins resolving a single target) hitting inventory range syntax that was never expanded by the inventory layer.

Common situations: A playbook passes a range pattern like 'web[1:3]' directly to add_host, a module parameter, or a connection setting where only a single host is meaningful; the pattern failed to expand earlier (misconfigured inventory plugin or pattern used outside inventory context); user assumes bracket ranges are shell globbing rather than Ansible inventory syntax.

Related errors


AI-assisted analysis of ansible/ansible@9cf16a4aca (2026-08-15). Data as JSON: /api/errors/41b98ad498988fdb. Report an issue: GitHub.