oraios/serena · error
Pass either content or source_file_path
Error message
Pass either content or source_file_path
What it means
TextUtils.search_text requires the text to search: it accepts either raw content or a source_file_path it reads itself. If both are absent (content is None after optional file read) it raises ValueError, since searching an empty input would silently return no matches.
Solutions
- Pass source_file_path pointing to an existing file
- Or read the file yourself and pass content=<string>
- Validate inputs before the call and raise a clearer domain-specific error
- Fix callers that pass None after a failed file read
Example fix
// before
TextUtils.search_text('pattern') # ValueError
// after
TextUtils.search_text('pattern', source_file_path='src/main.py')
# or
content = open('src/main.py').read()
TextUtils.search_text('pattern', content=content) Defensive patterns
Strategy: validation
Validate before calling
def safe_search(pattern: str, path: str | None = None, content: str | None = None):
if content is None and path is None:
raise ValueError("search_text needs content or source_file_path")
return TextUtils.search_text(pattern, source_file_path=path, content=content) Try / catch
try:
matches = TextUtils.search_text(pattern, source_file_path=path)
except ValueError as e:
log.error("search_text misused: %s", e) Prevention
- Always pass either content or source_file_path explicitly
- Check that the source file exists before passing its path
- Wrap search helpers so None inputs fail fast with a clear message
When it happens
Trigger: Calling search_text(pattern) with neither content nor source_file_path, or with source_file_path set but content explicitly None and the path handling skipped — e.g. search_text(pattern, content=None, source_file_path=None).
Common situations: Programmatic callers passing variables that are None because a previous read failed; refactors changing the function signature; tests forgetting required arguments.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Invalid glob brace expression in
- Invalid glob brace expression in
- Invalid tool name
- Invalid topic
- Tool named ' ' not found.
AI-assisted analysis of oraios/serena@7fcbca7e62 (2026-08-29).
Data as JSON: /api/errors/6a82038fd7db0a97.
Report an issue: GitHub.
Appendix: source
Thrown at src/serena/util/text_utils.py:145
"""
Search for a pattern in text content. Supports both regex and glob-like patterns.
:param pattern: Pattern to search for (regex or glob-like pattern)
:param content: The text content to search. May be None if source_file_path is provided.
:param source_file_path: Optional path to the source file. If content is None,
this has to be passed and the file will be read.
:param context_lines_before: Number of context lines to include before matches
:param context_lines_after: Number of context lines to include after matches
:param multiline: whether to apply multi-line matching, enabling the flags re.DOTALL and re.MULTILINE
:return: List of `TextSearchMatch` objects
:raises: ValueError if the pattern is not valid
"""
if source_file_path and content is None:
with open(source_file_path) as f:
content = f.read()
if content is None:
raise ValueError("Pass either content or source_file_path")
matches = []
lines = TextUtils.split_lines(content)
total_lines = len(lines)
# For multiline matches, optionally use DOTALL so '.' matches newlines
flags = (re.MULTILINE | re.DOTALL) if multiline else 0
compiled_pattern = re.compile(pattern, flags)
# Search across the entire content as a single string
for match in compiled_pattern.finditer(content):
start_pos = match.start()
end_pos = match.end()
# Find the line numbers for the start and end positions
start_line_num = TextUtils.get_line_from_index(content, start_pos)
end_line_num = TextUtils.get_line_from_index(content, end_pos)
if end_line_num > start_line_num and TextUtils.get_line_col_from_index(content, end_pos)[1] == 0:
# `end_pos` is exclusive, so if it is at the start of a line, the match ends with theView on GitHub (pinned to 7fcbca7e62)