OpenBMB/ChatDev · error · ValueError
start_line is required for each edit
Error message
start_line is required for each edit
What it means
Every edit entry must contain a usable start_line; _normalize_edits does int(item["start_line"]) and maps KeyError (missing key), TypeError (None), and ValueError (non-numeric string) to this ValueError. The line is 1-indexed. Without it the library cannot locate the edit target.
Source
Thrown at functions/function_calling/file.py:911
body = line.rstrip("\r\n")
numbered.append(f"{start_line + idx}:{body}")
rendered = newline_style.join(numbered)
if preserve_trailing_newline and numbered:
rendered += newline_style
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(),
)View on GitHub (pinned to 4fb2db0ea9)
Solutions
- Add an integer start_line (1-indexed) to every edit dict
- If lines come from a 0-based editor API, add 1 before sending
- Validate payload shape (required keys present and int-coercible) before calling
Example fix
# before
apply_text_edits(path="a.py", edits=[{"end_line": 5, "replacement": "x"}])
# after
apply_text_edits(path="a.py", edits=[{"start_line": 4, "end_line": 5, "replacement": "x"}]) Defensive patterns
Strategy: validation
Validate before calling
for e in edits:
if "start_line" not in e or not int(e["start_line"]):
raise ValueError("edit missing start_line")
apply_text_edits(path=path, edits=edits) Type guard
def edits_have_start_line(edits) -> bool:
return all(
isinstance(e, dict) and "start_line" in e
and str(e["start_line"]).strip().lstrip("-").isdigit()
for e in edits
) Try / catch
try:
apply_text_edits(path=path, edits=edits)
except ValueError as e:
if "start_line is required" in str(e):
# fill in or recompute start_line, then retry
...
raise Prevention
- Always include start_line (1-indexed) in every edit dict
- Convert 0-based editor ranges with +1 at the boundary
- Schema-validate tool payloads with required fields
When it happens
Trigger: Omitting start_line from an edit dict; passing start_line=None; passing start_line="abc" or "3-4"; using 0-based line numbers from an editor API and sending end_line only.
Common situations: Hand-built edit dicts missing keys; LLM-generated tool args that skip start_line; converting from an editor's 0-based Range and dropping the field; numeric strings from JSON that contain whitespace or ranges.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- tooling requires config block
- at least one edit instruction is required
- each edit entry must be a mapping object
- end_line must be an integer
- end_line must be >= start_line - 1
AI-assisted analysis of OpenBMB/ChatDev@4fb2db0ea9 (2026-08-27).
Data as JSON: /api/errors/171a4372230a8b3e.
Report an issue: GitHub.