oraios/serena · error · ValueError
Body end position is not defined for {self}
Error message
Body end position is not defined for {self} What it means
Strict counterpart of the body-start accessor: get_body_end_position_or_raise raises when the symbol's body end position is None. Used by replace_body, insert_after_symbol and delete_symbol, which need a valid end to compute the edit range.
Source
Thrown at src/serena/symbol.py:120
def name(self) -> str:
pass
def get_body_start_position_or_raise(self) -> PositionInFile:
"""
Get the start position of the symbol body, raising an error if it is not defined.
"""
pos = self.get_body_start_position()
if pos is None:
raise ValueError(f"Body start position is not defined for {self}")
return pos
def get_body_end_position_or_raise(self) -> PositionInFile:
"""
Get the end position of the symbol body, raising an error if it is not defined.
"""
pos = self.get_body_end_position()
if pos is None:
raise ValueError(f"Body end position is not defined for {self}")
return pos
@abstractmethod
def is_neighbouring_definition_separated_by_empty_line(self) -> bool:
"""
:return: whether a symbol definition of this symbol's kind is usually separated from the
previous/next definition by at least one empty line.
"""
class NamePathComponent:
def __init__(self, name: str, overload_idx: int | None = None) -> None:
self.name = name
self.overload_idx = overload_idx
def __repr__(self) -> str:
if self.overload_idx is not None:
return f"{self.name}[{self.overload_idx}]"View on GitHub (pinned to 7fcbca7e62)
Solutions
- Verify get_body_end_position() is not None before the mutating call
- Target only complete definitions (functions, classes, methods)
- Re-resolve the symbol after prior edits since stale positions can invalidate ranges
Example fix
// before
symbol.insert_after_symbol(new_code)
// after
if symbol.get_body_end_position() is not None:
symbol.insert_after_symbol(new_code) Defensive patterns
Strategy: type-guard
Validate before calling
if symbol.get_body_end_position() is None:
raise SkipSymbol(f"no end position: {symbol.get_name_path()}") Type guard
def has_editable_body(symbol) -> bool:
return symbol.get_body_start_position() is not None and symbol.get_body_end_position() is not None Try / catch
try:
symbol.insert_after_symbol(new_code)
except ValueError as e:
if "Body end position is not defined" in str(e):
handle_bodyless_symbol(symbol)
else:
raise Prevention
- Only insert/delete around complete definitions
- Check both body start and end before any range-based edit
- Re-resolve symbols after earlier edits to avoid stale ranges
When it happens
Trigger: insert_after_symbol/replace_body/delete_symbol on symbols whose end position is unavailable (body-less constructs, incomplete language-server ranges).
Common situations: Same as body-start: non-definitional symbols, languages with partial range support, stale symbol handles after file edits.
Related errors
- Body start position is not defined for {self}
- Body line numbers could not be determined for {self.get_name
- No symbol matching '{name_path_pattern}' found
- Found multiple {len(symbol_candidates)} symbols matching '{n
- FindSymbolTool returned no results
AI-assisted analysis of oraios/serena@7fcbca7e62 (2026-08-29).
Data as JSON: /api/errors/73fd4d572fa5314d.
Report an issue: GitHub.