{"record":{"id":"91409ce70cf6ba5d","repo":"ArchiveBox/ArchiveBox","slug":"archiveresult-chunk-index-must-be-less-than-chunk","errorCode":null,"errorMessage":"ArchiveResult chunk_index must be less than chunk_count","messagePattern":"ArchiveResult chunk_index must be less than chunk_count","errorType":"http","errorClass":"HttpError","httpStatus":400,"severity":"error","filePath":"archivebox/api/v1_core.py","lineNumber":442,"sourceCode":"            \"chunk_index\",\n        )\n        chunk_count = _parse_archiveresult_upload_int(\n            _get_archiveresult_upload_form_value(request, \"chunk_count\"),\n            \"chunk_count\",\n        )\n        chunk_offset = _parse_archiveresult_upload_int(\n            _get_archiveresult_upload_form_value(request, \"chunk_offset\"),\n            \"chunk_offset\",\n        )\n        chunk_total_size = _parse_archiveresult_upload_int(\n            _get_archiveresult_upload_form_value(request, \"chunk_total_size\"),\n            \"chunk_total_size\",\n        )\n\n        if chunk_count < 1:\n            raise HttpError(400, \"ArchiveResult chunk_count must be at least 1\")\n        if chunk_index >= chunk_count:\n            raise HttpError(400, \"ArchiveResult chunk_index must be less than chunk_count\")\n        if chunk_total_size and chunk_offset > chunk_total_size:\n            raise HttpError(400, \"ArchiveResult chunk_offset cannot exceed chunk_total_size\")\n\n        if chunk_index == 0 and chunk_offset == 0 and storage.exists(relative_output_path):\n            storage.delete(relative_output_path)\n\n        current_size = storage.size(relative_output_path) if storage.exists(relative_output_path) else 0\n        if current_size != chunk_offset:\n            raise HttpError(\n                409,\n                f\"ArchiveResult chunk offset mismatch for {relative_output_path}: expected {current_size}, got {chunk_offset}\",\n            )\n\n        Path(storage.path(relative_output_path)).parent.mkdir(parents=True, exist_ok=True)\n        with storage.open(relative_output_path, \"ab\") as destination:\n            for chunk in uploaded_file.chunks():\n                destination.write(chunk)\n","sourceCodeStart":424,"sourceCodeEnd":460,"githubUrl":"https://github.com/ArchiveBox/ArchiveBox/blob/74564b28220090664f919479e82cbf454125fa34/archivebox/api/v1_core.py#L424-L460","documentation":"chunk_index is zero-based and must satisfy chunk_index < chunk_count. Sending an index beyond the declared total chunk count fails this check, guarding against off-by-one or duplicated final-chunk sends.","triggerScenarios":"chunk_count=3 but chunk_index=3 (client looped one extra time); client recomputed chunk_count smaller mid-upload (file changed) while continuing with old indices; stale retry of a chunk after a corrected count.","commonSituations":"Race where the file was resized/re-chunked during upload; retry logic re-running the loop after the last chunk already succeeded; misreading zero-based indexing and using 1-based indices.","solutions":["Ensure chunk_index ranges 0..chunk_count-1 and the same chunk_count is sent on every chunk request","Fix client loop bounds (i < chunkCount, zero-based)","Re-start the upload if the file changed and chunk_count was recalculated"],"exampleFix":"// before\nfor (let i = 0; i <= chunkCount; i++) await sendChunk(i)\n// after\nfor (let i = 0; i < chunkCount; i++) await sendChunk(i, chunkCount)","handlingStrategy":"validation","validationCode":"if (!Number.isInteger(i) || i < 0 || i >= chunkCount) throw new Error(`chunk_index ${i} out of range 0..${chunkCount - 1}`);","typeGuard":"const inRange = (i: number, n: number): boolean => Number.isInteger(i) && i >= 0 && i < n;","tryCatchPattern":"if (res.status === 400 && /chunk_index must be less than chunk_count/.test(await res.text())) throw new Error('Loop bounds or re-chunking desync — restart the upload with consistent chunk_count');","preventionTips":["Zero-based loops with i < chunkCount","Send identical chunk_count on all requests","Restart the whole upload if the file changed mid-flight"],"tags":["http","chunked-upload","validation"],"backgroundTag":"chunked-upload-parameter-mismatch","analyzedSha":"74564b28220090664f919479e82cbf454125fa34","analyzedAt":"2026-08-28T23:56:51.556Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}