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

  1. Add an integer start_line (1-indexed) to every edit dict
  2. If lines come from a 0-based editor API, add 1 before sending
  3. 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

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


AI-assisted analysis of OpenBMB/ChatDev@4fb2db0ea9 (2026-08-27). Data as JSON: /api/errors/171a4372230a8b3e. Report an issue: GitHub.