OpenBMB/ChatDev · error · ValueError
end_line must be an integer
Error message
end_line must be an integer
What it means
The optional end_line field, when present, must be coercible to an integer. _normalize_edits runs int(end_line_raw) and converts TypeError/ValueError into this error, e.g. None, a non-numeric string, or a nested object. Note that int() accepts numeric strings like "12", so only genuinely non-integer values fail.
Source
Thrown at functions/function_calling/file.py:916
return rendered
def _normalize_edits(edits: Sequence[Mapping[str, Any]]) -> List[TextEdit]:
if not edits:
raise ValueError("at least one edit instruction is required")
normalized: List[TextEdit] = []
for item in edits:
if not isinstance(item, Mapping):
raise ValueError("each edit entry must be a mapping object")
try:
start_line = int(item["start_line"])
except (KeyError, TypeError, ValueError) as exc:
raise ValueError("start_line is required for each edit") from exc
end_line_raw = item.get("end_line", start_line)
try:
end_line = int(end_line_raw)
except (TypeError, ValueError) as exc:
raise ValueError("end_line must be an integer") from exc
if start_line < 1:
raise ValueError("start_line must be >= 1")
if end_line < start_line - 1:
raise ValueError("end_line must be >= start_line - 1")
replacement = item.get("replacement", "")
if not isinstance(replacement, str):
raise ValueError("replacement must be a string")
normalized.append(
TextEdit(
start_line=start_line,
end_line=end_line,
replacement_lines=replacement.splitlines(),
)
)
normalized.sort(key=lambda edit: (edit.start_line, edit.end_line))
_validate_edit_ranges(normalized)
return normalizedView on GitHub (pinned to 4fb2db0ea9)
Solutions
- Pass end_line as an integer or omit it (it defaults to start_line)
- To extend to end of file, pass the actual last line number, not null or 'EOF'
- Validate that end_line is an int or int-coercible string before calling
Example fix
# before
apply_text_edits(path="a.py", edits=[{"start_line": 2, "end_line": None, "replacement": "x"}])
# after
apply_text_edits(path="a.py", edits=[{"start_line": 2, "end_line": 2, "replacement": "x"}]) Defensive patterns
Strategy: validation
Validate before calling
for e in edits:
if "end_line" in e and e["end_line"] is None:
del e["end_line"] # default to start_line
apply_text_edits(path=path, edits=edits) Type guard
def end_lines_valid(edits) -> bool:
return all(
e.get("end_line", e.get("start_line")) is not None
and str(e.get("end_line", 0)).lstrip("-").replace(".", "", 1).isdigit()
for e in edits
) Try / catch
try:
apply_text_edits(path=path, edits=edits)
except ValueError as e:
if "end_line must be an integer" in str(e):
for ed in edits:
if "end_line" in ed: ed["end_line"] = int(ed["end_line"])
apply_text_edits(path=path, edits=edits)
else:
raise Prevention
- Omit end_line rather than passing null
- Coerce numeric strings to int at payload-build time
- For 'to EOF', pass the file's actual last line number
When it happens
Trigger: Passing end_line=None; end_line="5-7" or "abc"; end_line as a dict/list from malformed JSON; float strings like "1.5" (int('1.5') raises ValueError).
Common situations: LLM tool args with stringly-typed line ranges; JSON payloads where end_line was serialized as a range string; schemas that declare end_line as any/nullable and callers pass null meaning 'to EOF' (not supported).
Understand the failure class
Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.
Related errors
- each edit entry must be a mapping object
- replacement must be a string
- at least one edit instruction is required
- start_line is required for each edit
- end_line must be >= start_line - 1
AI-assisted analysis of OpenBMB/ChatDev@4fb2db0ea9 (2026-08-27).
Data as JSON: /api/errors/8f57705825367d92.
Report an issue: GitHub.