{"record":{"id":"3fea95f581dbc2a0","repo":"remotion-dev/remotion","slug":"canvas-capture-chunk-index-1-is-missing","errorCode":null,"errorMessage":"Canvas capture chunk ${index + 1} is missing.","messagePattern":"Canvas capture chunk (.+?) is missing\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/canvas-capture-extension/src/receiver.ts","lineNumber":62,"sourceCode":"\t}\n\n\twindow.postMessage(\n\t\t{\n\t\t\ttype: `${MESSAGE_PREFIX}-start`,\n\t\t\tcaptureId: id,\n\t\t\tfilename: metadata.filename,\n\t\t\tmimeType: metadata.mimeType,\n\t\t\tchunks: metadata.chunks,\n\t\t},\n\t\twindow.location.origin,\n\t);\n\n\tfor (let index = 0; index < metadata.chunks; index++) {\n\t\tconst key = getChunkKey(id, index);\n\t\tconst storedChunk = await chrome.storage.local.get(key);\n\t\tconst chunk = storedChunk[key];\n\t\tif (typeof chunk !== 'string') {\n\t\t\tthrow new Error(`Canvas capture chunk ${index + 1} is missing.`);\n\t\t}\n\n\t\twindow.postMessage(\n\t\t\t{\n\t\t\t\ttype: `${MESSAGE_PREFIX}-chunk`,\n\t\t\t\tcaptureId: id,\n\t\t\t\tindex,\n\t\t\t\tdata: chunk,\n\t\t\t},\n\t\t\twindow.location.origin,\n\t\t);\n\t\tawait chrome.storage.local.remove(key);\n\t}\n\n\twindow.postMessage(\n\t\t{type: `${MESSAGE_PREFIX}-complete`, captureId: id},\n\t\twindow.location.origin,\n\t);","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/canvas-capture-extension/src/receiver.ts#L44-L80","documentation":"While streaming chunks, the receiver loops `metadata.chunks` times, reads each chunk key via `getChunkKey(id, index)`, and requires the stored value to be a string. If a chunk is absent or not a string, it throws with the 1-based index. Each successfully posted chunk is removed from storage, so this is also raised if a chunk was already consumed or evicted.","triggerScenarios":"Requesting the same capture twice (first request removes chunks, second finds them missing); chrome.storage.local evicted individual chunks under quota; a chunk write was interrupted so it never persisted; metadata.chunks overstates the actual number of stored chunks.","commonSituations":"Replaying a capture after partial consumption; storage pressure evicting entries mid-stream; extension or browser closed mid-write; concurrent receivers consuming the same id.","solutions":["Request each capture id only once — chunks are deleted after being posted.","Ensure storage has enough quota for all chunks before starting a large capture.","Do not run two receivers for the same capture id concurrently.","Re-record the capture if chunks were partially lost."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"async function allChunksPresent(id: string, chunks: number): Promise<boolean> {\n  for (let i = 0; i < chunks; i++) {\n    const key = `capture:${id}:chunk:${i}`;\n    const v = (await chrome.storage.local.get(key))[key];\n    if (typeof v !== 'string') return false;\n  }\n  return true;\n}","typeGuard":null,"tryCatchPattern":"try {\n  await receiver.stream(id);\n} catch (e) {\n  if (e instanceof Error && /chunk .* is missing/.test(e.message)) {\n    // chunks are consumed on read; do not retry the same id.\n    await reRecord();\n  }\n  throw e;\n}","preventionTips":["Consume each capture id exactly once.","Avoid concurrent receivers for the same id.","Keep storage within quota."],"tags":["canvas-capture","chrome-storage","chunks","validation"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}