home-assistant/core · error · ValueError
Invalid MAC address
Error message
Invalid MAC address
What it means
Plain ValueError('Invalid MAC address') from the mac_address helper: it accepts MACs of length 17 (colon/dash separated pairs), 14, or 12 hex chars, normalizes them, then calls bytes.fromhex. Anything else — wrong length or non-hex content — raises. It is used to parse device MACs (e.g. from config entries or discovery) before .hex() unique-id generation.
Source
Thrown at homeassistant/components/broadlink/helpers.py:29
def data_packet(value):
"""Decode a data packet given for a Broadlink remote."""
value = cv.string(value)
extra = len(value) % 4
if extra > 0:
value = value + ("=" * (4 - extra))
return b64decode(value)
def mac_address(mac):
"""Validate and convert a MAC address to bytes."""
mac = cv.string(mac)
if len(mac) == 17:
mac = "".join(mac[i : i + 2] for i in range(0, 17, 3))
elif len(mac) == 14:
mac = "".join(mac[i : i + 4] for i in range(0, 14, 5))
elif len(mac) != 12:
raise ValueError("Invalid MAC address")
return bytes.fromhex(mac)
def format_mac(mac):
"""Format a MAC address."""
return ":".join([format(octet, "02x") for octet in mac])
def import_device(hass, host):
"""Create a config flow for a device."""
configured_hosts = {
entry.data.get(CONF_HOST) for entry in hass.config_entries.async_entries(DOMAIN)
}
if host not in configured_hosts:
task = hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_IMPORT},View on GitHub (pinned to 58a3fdb3ea)
Solutions
- Re-enter the MAC exactly as printed on the device label, e.g. AA:BB:CC:DD:EE:FF (17 chars) or 12 bare hex digits.
- Strip whitespace/newlines before passing the value.
- Verify length: 12, 14, or 17 characters only; separators must be consistent so normalization yields valid hex.
- If it comes from discovery data, capture the raw payload and open a core issue for the device model.
Example fix
// before
mac_bytes = mac_address("AA:BB:CC:DD:EE") # too short
// after
mac_bytes = mac_address("AA:BB:CC:DD:EE:FF") Defensive patterns
Strategy: validation
Validate before calling
import re
def is_valid_broadlink_mac(mac: str) -> bool:
"""True for 12/14/17-char strings whose stripped form is pure hex."""
if not isinstance(mac, str):
return False
stripped = re.sub(r"[:.\-\s]", "", mac)
return len(mac) in (12, 14, 17) and re.fullmatch(r"[0-9a-fA-F]+", stripped) is not None and len(stripped) == 12 Type guard
def is_mac_string(value: object) -> bool:
"""Narrow arbitrary config input to an acceptable MAC string."""
return isinstance(value, str) and bool(re.fullmatch(r"[0-9A-Fa-f:.\-\s]{12,17}", value)) Try / catch
try:
mac_bytes = mac_address(user_input[CONF_MAC])
except ValueError:
errors[CONF_MAC] = "invalid_mac" # show field error in the form instead of crashing Prevention
- Copy MACs from the device label and strip whitespace before use.
- Wrap mac_address() calls in form validation so users get field-level feedback.
- Reject empty/None early at the UI boundary.
When it happens
Trigger: mac_address() receives a string shorter/longer than 12/14/17 characters, or containing non-hex characters (e.g. 'ZZ:...', or a 16-char truncated MAC, or empty string). Callers include import_device / device setup paths that parse user-supplied or discovery-supplied hosts.
Common situations: Manual config with a typo'd MAC, discovery payload with an atypical separator pattern whose stripped length is not 12/14/17, copy-paste including whitespace, or a None/empty value passed by a broken caller.
Related errors
- notify_missing_argument
- frequency_not_supported
- You need to specify a device
- Command not found: {cmd!r}
- Invalid code: {code!r}
AI-assisted analysis of home-assistant/core@58a3fdb3ea (2026-08-14).
Data as JSON: /api/errors/b25a1719af74e9fb.
Report an issue: GitHub.