{"record":{"id":"8b1e78a70540015b","repo":"Hmbown/CodeWhale","slug":"overlap-must-be-smaller-than-max-chars","errorCode":null,"errorMessage":"overlap must be smaller than max_chars","messagePattern":"overlap must be smaller than max_chars","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"crates/tui/src/repl/runtime.rs","lineNumber":897,"sourceCode":"        snippet_start = max(0, start - 120)\n        snippet_end = min(len(_context), end + 120)\n        hits.append({\n            \"index\": i,\n            \"start\": start,\n            \"end\": end,\n            \"match\": m.group(0),\n            \"snippet\": _context[snippet_start:snippet_end],\n        })\n    return hits\n\ndef chunk(max_chars=20000, overlap=0):\n    \"\"\"Return full-coverage input chunks with index/start/end/text fields.\"\"\"\n    max_chars = int(max_chars)\n    overlap = max(0, int(overlap))\n    if max_chars <= 0:\n        raise ValueError(\"max_chars must be > 0\")\n    if overlap >= max_chars:\n        raise ValueError(\"overlap must be smaller than max_chars\")\n    chunks = []\n    start = 0\n    idx = 0\n    total = len(_context)\n    while start < total:\n        end = min(total, start + max_chars)\n        chunks.append({\"index\": idx, \"start\": start, \"end\": end, \"text\": _context[start:end]})\n        idx += 1\n        if end >= total:\n            break\n        start = end - overlap\n    return chunks\n\ndef chunk_context(max_chars=20000, overlap=0):\n    \"\"\"Compatibility alias for chunk().\"\"\"\n    return chunk(max_chars=max_chars, overlap=overlap)\n\ndef chunk_coverage(chunks):","sourceCodeStart":879,"sourceCodeEnd":915,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/repl/runtime.rs#L879-L915","documentation":"chunk() raises ValueError when overlap >= max_chars; negative overlap is clamped to 0 before the comparison. After each chunk the loop sets start = end - overlap, so with overlap at or above the window size start would never advance and the loop would never terminate. This check is an infinite-loop guard, not a style rule.","triggerScenarios":"Calling chunk(1000, 1000), chunk(500, 5000), or generated code setting overlap equal to the window 'so nothing is missed'.","commonSituations":"LLM-generated recall-maximizing configs; argument order mixups after refactors; configs written for tools where overlap may equal the window size.","solutions":["Use a strictly smaller overlap, e.g. chunk(20000, 200)","Scale overlap as a fraction of the window: overlap = max_chars // 10","Keep overlap 0 when full coverage is the goal; chunks already cover the input end to end"],"exampleFix":"# before\nchunk(max_chars=1000, overlap=1000)\n# after\nchunk(max_chars=1000, overlap=100)","handlingStrategy":"validation","validationCode":"max_chars = max(1, int(max_chars))\noverlap = max(0, min(int(overlap), max_chars - 1))\nchunks = chunk(max_chars, overlap)","typeGuard":null,"tryCatchPattern":"try:\n    chunks = chunk(max_chars, overlap)\nexcept ValueError:\n    chunks = chunk(max_chars, 0)  # overlap=0 always satisfies the guard","preventionTips":["Derive overlap as a fraction of the window (e.g. max_chars // 10)","Treat 0 <= overlap < max_chars as part of the API contract","Beware swapped arguments when refactoring chunk call sites"],"tags":["python","repl","validation","chunking","infinite-loop"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}