{"record":{"id":"cbc6f90f61b3a232","repo":"Aider-AI/aider","slug":"path-overlapping-or-out-of-order-chunk-detected","errorCode":null,"errorMessage":"{path}: Overlapping or out-of-order chunk detected. Current index {current_orig_line_idx}, chunk starts at {chunk_start_index}.","messagePattern":"(.+?): Overlapping or out-of-order chunk detected\\. Current index (.+?), chunk starts at (.+?)\\.","errorType":"exception","errorClass":"DiffError","httpStatus":null,"severity":"error","filePath":"aider/coders/patch_coder.py","lineNumber":665,"sourceCode":"        if action.type is not ActionType.UPDATE:\n            # Should not be called otherwise, but check for safety\n            raise DiffError(\"_apply_update called with non-update action\")\n\n        orig_lines = text.splitlines()  # Use splitlines to handle endings consistently\n        dest_lines: List[str] = []\n        current_orig_line_idx = 0  # Tracks index in orig_lines processed so far\n\n        # Sort chunks by their original index to apply them sequentially\n        sorted_chunks = sorted(action.chunks, key=lambda c: c.orig_index)\n\n        for chunk in sorted_chunks:\n            # chunk.orig_index is the absolute line number where the change starts\n            # (where the first deleted line was, or where inserted lines go if no deletes)\n            chunk_start_index = chunk.orig_index\n\n            if chunk_start_index < current_orig_line_idx:\n                # This indicates overlapping chunks or incorrect indices from parsing\n                raise DiffError(\n                    f\"{path}: Overlapping or out-of-order chunk detected.\"\n                    f\" Current index {current_orig_line_idx}, chunk starts at {chunk_start_index}.\"\n                )\n\n            # Add lines from original file between the last chunk and this one\n            dest_lines.extend(orig_lines[current_orig_line_idx:chunk_start_index])\n\n            # Verify that the lines to be deleted actually match the original file content\n            # (The parser should have used find_context, but double-check here)\n            num_del = len(chunk.del_lines)\n            actual_deleted_lines = orig_lines[chunk_start_index : chunk_start_index + num_del]\n\n            # Use the same normalization as find_context_core for comparison robustness\n            norm_chunk_del = [_norm(s).strip() for s in chunk.del_lines]\n            norm_actual_del = [_norm(s).strip() for s in actual_deleted_lines]\n\n            if norm_chunk_del != norm_actual_del:\n                # This indicates the context matching failed or the file changed since parsing","sourceCodeStart":647,"sourceCodeEnd":683,"githubUrl":"https://github.com/Aider-AI/aider/blob/5dc9490bb35f9729ef2c95d00a19ccd30c26339c/aider/coders/patch_coder.py#L647-L683","documentation":"Inside _apply_update: after sorting chunks by orig_index, a chunk's start line is before the file position already consumed by a previous chunk. The parser should never produce overlapping/backwards chunks, so this guards against parser bugs or externally built chunk lists with wrong absolute indices.","triggerScenarios":"Two chunks whose orig_index values overlap given their del_lines lengths; chunks with relative (not absolute) indices passed in; duplicated chunks after manual manipulation.","commonSituations":"Building PatchAction.chunks programmatically with peek-relative indices instead of the parser's absolute-adjusted ones; replaying captured chunks onto a different base text; parser regressions with fuzzy matches assigning wrong found_index.","solutions":["If constructing chunks manually, ensure orig_index is the absolute 0-based line in the original file and chunks are non-overlapping and in order","Reparse the patch from text so the parser computes indices via find_context","Shrink or merge overlapping edits into a single chunk"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"def chunks_non_overlapping(chunks) -> bool:\n    ordered = sorted(chunks, key=lambda c: c.orig_index)\n    cursor = 0\n    for c in ordered:\n        if c.orig_index < cursor:\n            return False\n        cursor = c.orig_index + len(c.del_lines)\n    return True","typeGuard":null,"tryCatchPattern":"try:\n    coder.apply_edits(edits)\nexcept ValueError as e:\n    if \"Overlapping or out-of-order chunk\" in str(e):\n        raise RuntimeError(\"chunk indices invalid; reparse patch from text\")\n    raise","preventionTips":["Use the parser (get_edits) rather than hand-building chunks so indices are absolute","When merging edits manually, recompute orig_index and check for overlaps","Sort and validate chunk ranges before apply"],"tags":["aider","patch","chunks","invariant"],"backgroundTag":null,"analyzedSha":"5dc9490bb35f9729ef2c95d00a19ccd30c26339c","analyzedAt":"2026-08-15T05:40:10.498Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}