home-assistant/core · error · ValueError

Local name matchers may not have patterns in the first {LOCA

Error message

Local name matchers may not have patterns in the first {LOCAL_NAME_MIN_MATCH_LENGTH} characters because they would match too broadly ({local_name})

What it means

ValueError from _local_name_to_index_key (bluetooth matchers): the first LOCAL_NAME_MIN_MATCH_LENGTH (=3) characters of a local_name matcher contain a glob pattern character ('*' or '['). Such short wildcards would land in the broad index buckets and degrade matching performance for every advertisement, so they are rejected at registration time.

Source

Thrown at homeassistant/components/bluetooth/match.py:391

        for matcher in self.address.get(service_info.address, []):
            if ble_device_matches(matcher, service_info):
                matches.append(matcher)
        for matcher in self.connectable:
            if ble_device_matches(matcher, service_info):
                matches.append(matcher)
        return matches


def _local_name_to_index_key(local_name: str) -> str:
    """Convert a local name to an index.

    We check the local name matchers here and raise a ValueError
    if they try to setup a matcher that will is overly broad
    as would match too many devices and cause a performance hit.
    """
    match_part = local_name[:LOCAL_NAME_MIN_MATCH_LENGTH]
    if "*" in match_part or "[" in match_part:
        raise ValueError(
            "Local name matchers may not have patterns in the first "
            f"{LOCAL_NAME_MIN_MATCH_LENGTH} characters because they "
            f"would match too broadly ({local_name})"
        )
    return match_part


def ble_device_matches(
    matcher: BluetoothMatcherOptional,
    service_info: BluetoothServiceInfoBleak,
) -> bool:
    """Check if a ble device and advertisement_data matches the matcher."""
    # Don't check address here since all callers already
    # check the address and we don't want to double check
    # since it would result in an unreachable reject case.
    if matcher.get(CONNECTABLE, True) and not service_info.connectable:
        return False

View on GitHub (pinned to 58a3fdb3ea)

Solutions

  1. Anchor the pattern with at least 3 literal leading characters: 'Flower care*' instead of '*care*'
  2. Prefer matching on service_uuid or manufacturer instead of local_name for broad device families
  3. If you must match a short/prefix-variable name, match on the full literal local_name or use the company_id

Example fix

# before
BluetoothMatcher(local_name="* sensor")

# after
BluetoothMatcher(local_name="LYWSD03*")
Defensive patterns

Strategy: validation

Validate before calling

from homeassistant.components.bluetooth.match import LOCAL_NAME_MIN_MATCH_LENGTH

def local_name_matcher_ok(local_name: str) -> bool:
    return not any(c in local_name[:LOCAL_NAME_MIN_MATCH_LENGTH] for c in ("*", "["))

Try / catch

try:
    matcher = BluetoothMatcher(local_name=name)
except ValueError as err:
    if "patterns in the first" in str(err):
        # lengthen the literal prefix or match on service_uuid instead

Prevention

When it happens

Trigger: Registering a BluetoothMatcher with local_name='* Sensor' or 'Fo[ox]' — anything where chars 0-2 include * or [ — via the matcher API, integration config (e.g. bluetooth_admin / passive BLE integrations), or an integration's async_register_callback matcher.

Common situations: Integration authors writing matchers like local_name: '*flower care*'; users configuring broad name filters hoping to catch many devices; porting matcher YAML from other platforms that allow leading wildcards.

Related errors


AI-assisted analysis of home-assistant/core@58a3fdb3ea (2026-08-14). Data as JSON: /api/errors/8c497c2a61bd4b6f. Report an issue: GitHub.