oraios/serena · error
Regex must contain exactly one group to capture the position
Error message
Regex must contain exactly one group to capture the position, but found {len(match.groups())} groups. What it means
find_text_coordinates() returns the position of the regex's captured group; the pattern must therefore contain exactly one capture group. Zero groups (nothing to report position of) or 2+ groups make the intended coordinate undefined, so it raises.
Source
Thrown at src/serena/util/text_utils.py:673
: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
- Wrap the token whose position you want in exactly one group: r'... (target) ...'
- Convert auxiliary grouping parentheses to non-capturing (?:...)
- Count groups with re.compile(pattern).groups before calling
Example fix
// before find_text_coordinates(content, r'def (my_func)(args)') # 2 groups // after find_text_coordinates(content, r'def (my_func)(?:args)') # exactly 1 group
Defensive patterns
Strategy: validation
Validate before calling
g = re.compile(regex).groups
if g != 1:
raise ValueError(f'locator regex needs exactly one capture group, has {g}') Type guard
def has_single_group(regex: str) -> bool:
return re.compile(regex).groups == 1 Try / catch
try:
coords = find_text_coordinates(content, regex)
except ValueError as e:
if 'exactly one group' in str(e):
coords = find_text_coordinates(content, f'({regex})') # wrap single group
else:
raise Prevention
- Use non-capturing (?:...) for context groups
- Check re.compile(p).groups == 1 before calling
- Keep locator and search regexes separate
When it happens
Trigger: Passing a regex with no parentheses, or with multiple capture groups like r'(def) (foo)', to find_text_coordinates.
Common situations: Reusing a search-only regex as a locator without adding a capturing group; adding non-capturing context as parentheses instead of (?:...).
Related errors
- Match is ambiguous: the search pattern matches multiple over
- Error: No matches of search expression found.
- Expression matches {n} occurrences. Please revise the expres
- No match found for regex: {regex}
- Match must be unique; found {len(matches)} matches for regex
AI-assisted analysis of oraios/serena@7fcbca7e62 (2026-08-29).
Data as JSON: /api/errors/d58368a8e602bebb.
Report an issue: GitHub.