oraios/serena · error

Match must be unique; found {len(matches)} matches for regex

Error message

Match must be unique; found {len(matches)} matches for regex: {regex}

What it means

find_text_coordinates() with require_unique=True demands exactly one match so the returned coordinates are unambiguous. When the regex matches multiple times it cannot know which occurrence's position to return, so it raises listing the match count.

Source

Thrown at src/serena/util/text_utils.py:670

    """
    Finds the line and column number of the first match of a regex pattern in the given content.

    :param content: the text content to search through
    :param regex: the regular expression pattern to search for; it must match part of a single line,
        and contain exactly one group that captures the position of interest (e.g., the exact variable name to find the coordinates of)
    :param require_unique: if True, raises an error if not exactly one match is found;
        if False, returns None if no match is found, and returns the coordinates of the first match if multiple matches are found
    :return: the coordinates of the match or None
    """
    pattern = re.compile(regex, flags=re.MULTILINE | re.DOTALL)
    matches = list(pattern.finditer(content))
    if len(matches) == 0:
        if require_unique:
            raise ValueError(f"No match found for regex: {regex}")
        return None
    else:
        if require_unique and len(matches) > 1:
            raise ValueError(f"Match must be unique; found {len(matches)} matches for regex: {regex}")
        match = matches[0]
        if len(match.groups()) != 1:
            raise ValueError(f"Regex must contain exactly one group to capture the position, but found {len(match.groups())} groups.")
        index_in_content = match.start(1)
        line, col = TextUtils.get_line_col_from_index(content, index_in_content)
        return TextCoords(line, col)

View on GitHub (pinned to 7fcbca7e62)

Solutions

  1. Add unique context before/after the capture (enclosing component, class, or block)
  2. Narrow the searched content region to the relevant section before locating
  3. If any occurrence is acceptable, pass require_unique=False (first match is used)

Example fix

// before
find_text_coordinates(content, r'(save\(\))')  # matches in 3 components
// after
find_text_coordinates(content, r'component "header"[\s\S]*?(save\(\))')  # scoped to one block
Defensive patterns

Strategy: validation

Validate before calling

hits = re.findall(regex, content, flags=re.MULTILINE|re.DOTALL)
if len(hits) > 1:
    raise ValueError('locator matches multiple sites; add context or use require_unique=False')

Try / catch

try:
    coords = find_text_coordinates(content, regex)
except ValueError as e:
    if 'Match must be unique' in str(e):
        coords = find_text_coordinates(content, regex, require_unique=False)
    else:
        raise

Prevention

When it happens

Trigger: Calling find_text_coordinates with require_unique=True on a regex that matches 2+ locations, e.g. a generic method-name pattern that appears in several components.

Common situations: Repeated helper names across templates; same attribute like (click)="save()" in multiple places; overly broad patterns lacking component/section context.

Related errors


AI-assisted analysis of oraios/serena@7fcbca7e62 (2026-08-29). Data as JSON: /api/errors/831ff07477c5e9c8. Report an issue: GitHub.