ruby/ruby · error · InvalidAddressError
invalid zone identifier for address
Error message
invalid zone identifier for address
What it means
IPAddr#zone_id= assigns the zone identifier of an IPv6 address. The value must be nil (clears the zone) or a String matching the strict pattern of a percent sign followed by word characters only. Anything else - 'eth0' without %, '%eth 0' with a space, an Integer scope id - raises InvalidAddressError 'invalid zone identifier for address'.
Source
Thrown at lib/ipaddr.rb:583
# Returns the IPv6 zone identifier, if present.
# Raises InvalidAddressError if not an IPv6 address.
def zone_id
if @family == Socket::AF_INET6
@zone_id
else
raise InvalidAddressError, "not an IPv6 address"
end
end
# Returns the IPv6 zone identifier, if present.
# Raises InvalidAddressError if not an IPv6 address.
def zone_id=(zid)
if @family == Socket::AF_INET6
case zid
when nil, /\A%(\w+)\z/
@zone_id = zid
else
raise InvalidAddressError, "invalid zone identifier for address"
end
else
raise InvalidAddressError, "not an IPv6 address"
end
end
protected
# :stopdoc:
def begin_addr
@addr & @mask_addr
end
def end_addr
case @family
when Socket::AF_INET
@addr | (IN4MASK ^ @mask_addr)
when Socket::AF_INET6View on GitHub (pinned to 0e5b888e1c)
Solutions
- Prefix % when missing: zid = zid.start_with?('%') ? zid : "%#{zid}"
- Pass nil to clear the zone identifier
- Pre-validate against the accepted pattern before assigning
Example fix
# before
ip.zone_id = if_name # 'eth0' -> InvalidAddressError
# after
ip.zone_id = "%#{if_name}" Defensive patterns
Strategy: validation
Validate before calling
zid = nil if zid.nil?
zid = "%#{zid}" if zid.is_a?(String) && !zid.start_with?('%')
raise ArgumentError, 'bad zone id' unless zid.nil? || zid.match?(/\A%\w+\z/)
ip.zone_id = zid Type guard
def valid_zone_id?(v) v.nil? || (v.is_a?(String) && v.match?(/\A%\w+\z/)) end
Try / catch
begin ip.zone_id = zid rescue IPAddr::InvalidAddressError => e errors << e.message end
Prevention
- Always store zone ids with the leading % ('%eth0', not 'eth0')
- Pass nil to clear instead of an empty string
- Remember \w excludes '.', '-', and ':' - pre-validate names like 'eth0.100'
When it happens
Trigger: ip.zone_id = 'eth0' (missing leading %); ip.zone_id = '%fe80::1' (colons are not word characters); ip.zone_id = 2 (Integer from if_nametoindex); strings with hyphens, dots, or spaces in the zone name.
Common situations: Passing interface names from Socket.getifaddrs or config straight through without the % sigil; APIs that return numeric scope ids; zone names containing '-' or '.' (e.g. 'eth0.100') which \w does not match.
Related errors
- not an IPv6 address
- not an IPv4 address: #{to_s}
- not an IPv6 address: #{to_s}
- address family is not same
- address family mismatch
AI-assisted analysis of ruby/ruby@0e5b888e1c (2026-08-21).
Data as JSON: /api/errors/7f6755f0beb1c129.
Report an issue: GitHub.