oraios/serena · error · ValueError

Found multiple {len(symbol_candidates)} symbols matching '{n

Error message

Found multiple {len(symbol_candidates)} symbols matching '{name_path_pattern}'. They are: 
{json.dumps([s.to_dict(kind=True, relative_path=include_rel_path) for s in symbol_candidates], indent=2)}

What it means

When find_unique finds more than one candidate and exactly one exact name-path match cannot disambiguate them, it raises with the full candidate list (kind + relative path) serialized as JSON so the caller can pick the right name_path.

Source

Thrown at src/serena/symbol.py:794

            name_path_pattern,
            include_kinds=include_kinds,
            exclude_kinds=exclude_kinds,
            substring_matching=substring_matching,
            within_relative_path=within_relative_path,
        )
        if len(symbol_candidates) == 1:
            return symbol_candidates[0]
        elif len(symbol_candidates) == 0:
            raise ValueError(f"No symbol matching '{name_path_pattern}' found")
        else:
            # There are multiple candidates.
            # If only one of the candidates has the given pattern as its exact name path, return that one
            exact_matches = [s for s in symbol_candidates if s.get_name_path() == name_path_pattern]
            if len(exact_matches) == 1:
                return exact_matches[0]
            # otherwise, raise an error
            include_rel_path = within_relative_path is not None
            raise ValueError(
                f"Found multiple {len(symbol_candidates)} symbols matching '{name_path_pattern}'. "
                "They are: \n" + json.dumps([s.to_dict(kind=True, relative_path=include_rel_path) for s in symbol_candidates], indent=2)
            )

    def find_by_location(self, location: LanguageServerSymbolLocation) -> LanguageServerSymbol | None:
        if location.relative_path is None:
            return None
        lang_server = self.get_language_server(location.relative_path)
        document_symbols = lang_server.request_document_symbols(location.relative_path)
        for symbol_dict in document_symbols.iter_symbols():
            symbol = LanguageServerSymbol(symbol_dict)
            if symbol.location == location:
                return symbol
        return None

    def find_referencing_symbols(
        self,
        name_path: str,

View on GitHub (pinned to 7fcbca7e62)

Solutions

  1. Pass the fully qualified name_path (e.g. "MyClass.my_method") so the exact-match disambiguation succeeds
  2. Narrow the search with within_relative_path to the file/directory containing the target
  3. Read the candidate list in the error message and retry with the exact name_path of the intended symbol

Example fix

// before
mgr.find_unique("to_dict")  # multiple hits
// after
mgr.find_unique("User.to_dict")
Defensive patterns

Strategy: validation

Validate before calling

matches = mgr.find_name_patterns(name_path)
if len(matches) > 1:
    raise AmbiguousSymbol(name_path, [m.get_name_path() for m in matches])

Try / catch

try:
    sym = mgr.find_unique(short_name)
except ValueError as e:
    if "Found multiple" in str(e):
        candidates = parse_candidates(e)
        sym = mgr.find_unique(disambiguate(candidates))
    else:
        raise

Prevention

When it happens

Trigger: Querying a short name like "handle" or "__init__" that exists in many classes/files; methods with the same name in base and derived classes; same-named symbols in different modules without qualifying the name path.

Common situations: Tools passing bare function names instead of dotted paths; large codebases with common helper names (run, main, to_dict); duplicate names across test and source trees.

Related errors


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