{"record":{"id":"ee71ef907c59eb63","repo":"OpenBMB/ChatDev","slug":"each-edit-entry-must-be-a-mapping-object","errorCode":null,"errorMessage":"each edit entry must be a mapping object","messagePattern":"each edit entry must be a mapping object","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"functions/function_calling/file.py","lineNumber":907,"sourceCode":"    preserve_trailing_newline: bool,\n) -> str:\n    numbered: List[str] = []\n    for idx, line in enumerate(lines):\n        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(","sourceCodeStart":889,"sourceCodeEnd":925,"githubUrl":"https://github.com/OpenBMB/ChatDev/blob/4fb2db0ea90375ce1059f44fe03ffbd191a7a169/functions/function_calling/file.py#L889-L925","documentation":"Each element of the edits sequence passed to apply_text_edits must be a mapping (dict-like) with start_line/end_line/replacement keys. _normalize_edits checks isinstance(item, Mapping) and raises ValueError when an entry is, e.g., a string, tuple, or list. This guards against malformed tool payloads before any file is touched.","triggerScenarios":"Passing edits as a list of strings ('replace line 3'), tuples, or JSON where each entry is an array instead of an object; double-wrapping edits as [[{...}]] so inner items are lists; deserializing JSON with entries that are not objects.","commonSituations":"LLM tool-call arguments that encode edits as arrays; converting between tuple-based and dict-based edit representations; copy-pasting an example where the edit body was a string instead of an object.","solutions":["Ensure every edit entry is a dict with at least start_line and optionally end_line/replacement","If JSON-serializing edits, use objects: {\"start_line\": 3, \"end_line\": 3, \"replacement\": \"...\"} not arrays","Validate/normalize the payload shape before calling apply_text_edits"],"exampleFix":"# before\napply_text_edits(path=\"a.py\", edits=[\"3: new text\"])\n# after\napply_text_edits(path=\"a.py\", edits=[{\"start_line\": 3, \"replacement\": \"new text\"}])","handlingStrategy":"type-guard","validationCode":"if not all(isinstance(e, dict) for e in edits):\n    edits = [e if isinstance(e, dict) else dict(e) for e in edits]  # or reject\napply_text_edits(path=path, edits=edits)","typeGuard":"from collections.abc import Mapping\n\ndef is_edit_list(edits) -> bool:\n    return isinstance(edits, (list, tuple)) and all(isinstance(e, Mapping) for e in edits)","tryCatchPattern":"try:\n    apply_text_edits(path=path, edits=edits)\nexcept ValueError as e:\n    raise TypeError(f\"malformed edits payload: {e}\") from e","preventionTips":["Define a JSON schema requiring each edit to be an object with required keys","Validate LLM/tool payloads before invoking file-mutating tools","Never pass tuples/strings as edit entries"],"tags":["validation","text-edit","type-mismatch"],"backgroundTag":"schema-validation-failed","analyzedSha":"4fb2db0ea90375ce1059f44fe03ffbd191a7a169","analyzedAt":"2026-08-27T14:35:29.622Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}