{"record":{"id":"171a4372230a8b3e","repo":"OpenBMB/ChatDev","slug":"start-line-is-required-for-each-edit","errorCode":null,"errorMessage":"start_line is required for each edit","messagePattern":"start_line is required for each edit","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"functions/function_calling/file.py","lineNumber":911,"sourceCode":"        body = line.rstrip(\"\\r\\n\")\n        numbered.append(f\"{start_line + idx}:{body}\")\n    rendered = newline_style.join(numbered)\n    if preserve_trailing_newline and numbered:\n        rendered += newline_style\n    return rendered\n\n\ndef _normalize_edits(edits: Sequence[Mapping[str, Any]]) -> List[TextEdit]:\n    if not edits:\n        raise ValueError(\"at least one edit instruction is required\")\n    normalized: List[TextEdit] = []\n    for item in edits:\n        if not isinstance(item, Mapping):\n            raise ValueError(\"each edit entry must be a mapping object\")\n        try:\n            start_line = int(item[\"start_line\"])\n        except (KeyError, TypeError, ValueError) as exc:\n            raise ValueError(\"start_line is required for each edit\") from exc\n        end_line_raw = item.get(\"end_line\", start_line)\n        try:\n            end_line = int(end_line_raw)\n        except (TypeError, ValueError) as exc:\n            raise ValueError(\"end_line must be an integer\") from exc\n        if start_line < 1:\n            raise ValueError(\"start_line must be >= 1\")\n        if end_line < start_line - 1:\n            raise ValueError(\"end_line must be >= start_line - 1\")\n        replacement = item.get(\"replacement\", \"\")\n        if not isinstance(replacement, str):\n            raise ValueError(\"replacement must be a string\")\n        normalized.append(\n            TextEdit(\n                start_line=start_line,\n                end_line=end_line,\n                replacement_lines=replacement.splitlines(),\n            )","sourceCodeStart":893,"sourceCodeEnd":929,"githubUrl":"https://github.com/OpenBMB/ChatDev/blob/4fb2db0ea90375ce1059f44fe03ffbd191a7a169/functions/function_calling/file.py#L893-L929","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\napply_text_edits(path=\"a.py\", edits=[{\"end_line\": 5, \"replacement\": \"x\"}])\n# after\napply_text_edits(path=\"a.py\", edits=[{\"start_line\": 4, \"end_line\": 5, \"replacement\": \"x\"}])","handlingStrategy":"validation","validationCode":"for e in edits:\n    if \"start_line\" not in e or not int(e[\"start_line\"]):\n        raise ValueError(\"edit missing start_line\")\napply_text_edits(path=path, edits=edits)","typeGuard":"def edits_have_start_line(edits) -> bool:\n    return all(\n        isinstance(e, dict) and \"start_line\" in e\n        and str(e[\"start_line\"]).strip().lstrip(\"-\").isdigit()\n        for e in edits\n    )","tryCatchPattern":"try:\n    apply_text_edits(path=path, edits=edits)\nexcept ValueError as e:\n    if \"start_line is required\" in str(e):\n        # fill in or recompute start_line, then retry\n        ...\n    raise","preventionTips":["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"],"tags":["validation","text-edit","missing-field"],"backgroundTag":"missing-required-field","analyzedSha":"4fb2db0ea90375ce1059f44fe03ffbd191a7a169","analyzedAt":"2026-08-27T14:35:29.622Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}