{"record":{"id":"4f77261f36c91f05","repo":"remotion-dev/remotion","slug":"render-did-not-finish-yet","errorCode":null,"errorMessage":"Render did not finish yet","messagePattern":"Render did not finish yet","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/lambda/src/api/download-media.ts","lineNumber":67,"sourceCode":"\t\tproviderSpecifics: ProviderSpecifics<AwsProvider>;\n\t\tforcePathStyle: boolean;\n\t},\n): Promise<DownloadMediaOutput> => {\n\tconst expectedBucketOwner = await input.providerSpecifics.getAccountId({\n\t\tregion: input.region,\n\t});\n\tconst overallProgress = await getOverallProgressFromStorage({\n\t\tbucketName: input.bucketName,\n\t\texpectedBucketOwner,\n\t\tregion: input.region,\n\t\trenderId: input.renderId,\n\t\tproviderSpecifics: input.providerSpecifics,\n\t\tforcePathStyle: input.forcePathStyle,\n\t\trequestHandler: input.requestHandler,\n\t});\n\n\tif (!overallProgress.renderMetadata) {\n\t\tthrow new Error('Render did not finish yet');\n\t}\n\n\tconst outputPath = path.resolve(process.cwd(), input.outPath);\n\tRenderInternals.ensureOutputDirectory(outputPath);\n\n\tconst {key, renderBucketName, customCredentials} = getExpectedOutName({\n\t\trenderMetadata: overallProgress.renderMetadata,\n\t\tbucketName: input.bucketName,\n\t\tcustomCredentials: input.customCredentials ?? null,\n\t\tbucketNamePrefix: REMOTION_BUCKET_PREFIX,\n\t});\n\n\tconst {sizeInBytes} = await lambdaDownloadFileWithProgress({\n\t\tbucketName: renderBucketName,\n\t\texpectedBucketOwner,\n\t\tkey,\n\t\tregion: input.region,\n\t\tonProgress: input.onProgress ?? (() => undefined),","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/lambda/src/api/download-media.ts#L49-L85","documentation":"The downloadMedia() / downloadVideo() / downloadAudio() functions call getOverallProgressFromStorage() to read the render metadata from S3. If renderMetadata is not present in the progress response, the render has not finished writing its final output metadata, so Remotion throws this error to prevent downloading a non-existent output file.","triggerScenarios":"Calling downloadMedia() (or the CLI npx remotion lambda download) before the render has completed. The render may still be in progress, may have failed, or the renderId/bucketName/region combination does not match an actual render. The overallProgress.renderMetadata field is only populated once the render finishes and writes its metadata file.","commonSituations":"Polling for a render that is still running; using a wrong renderId; pointing to the wrong bucket or region; render failed silently without writing metadata; calling downloadMedia() too early in a scripted pipeline without waiting for getRenderProgress() to report done.","solutions":["Wait until getRenderProgress() returns a result where done is true and fatalError is false before calling downloadMedia().","Verify the renderId, bucketName, and region match the values returned by renderMediaOnLambda().","Check getRenderProgress() for errors — the render may have failed rather than still being in progress.","Implement a polling loop around getRenderProgress() and only download once the render is confirmed complete."],"exampleFix":"// before\nawait downloadMedia({\n  region,\n  bucketName,\n  renderId,\n  outPath: './out.mp4',\n});\n\n// after\nlet done = false;\nwhile (!done) {\n  const progress = await getRenderProgress({\n    renderId,\n    bucketName,\n    region,\n  });\n  if (progress.fatalErrorEncountered) {\n    throw new Error(`Render failed: ${progress.errors.join(', ')}`);\n  }\n  done = progress.done;\n  if (!done) await new Promise((r) => setTimeout(r, 2000));\n}\nawait downloadMedia({\n  region,\n  bucketName,\n  renderId,\n  outPath: './out.mp4',\n});","handlingStrategy":"validation","validationCode":"import {getRenderProgress} from '@remotion/lambda'; // or lambda-client in v5\n\nasync function waitForRenderDone(region, bucketName, renderId): Promise<void> {\n  let done = false;\n  while (!done) {\n    const progress = await getRenderProgress({renderId, bucketName, region});\n    if (progress.fatalErrorEncountered) {\n      throw new Error(`Render failed: ${progress.errors.join('; ')}`);\n    }\n    done = progress.done;\n    if (!done) await new Promise((r) => setTimeout(r, 2000));\n  }\n}\n\nawait waitForRenderDone(region, bucketName, renderId);\nawait downloadMedia({region, bucketName, renderId, outPath});","typeGuard":"import type {OverallProgress} from '@remotion/lambda';\n\nfunction renderIsComplete(progress: OverallProgress): boolean {\n  return Boolean(progress.renderMetadata);\n}","tryCatchPattern":"try {\n  await downloadMedia({region, bucketName, renderId, outPath});\n} catch (err) {\n  if (err instanceof Error && err.message === 'Render did not finish yet') {\n    // Poll getRenderProgress() until done, then retry downloadMedia()\n  } else {\n    throw err;\n  }\n}","preventionTips":["Always poll getRenderProgress() until done is true before downloading.","Verify renderId, bucketName, and region match the render response exactly.","Check for fatalErrorEncountered in the progress response to detect failed renders early.","Build download into a polling loop with exponential backoff for large renders."],"tags":["lambda","aws","render","download","timing","precondition"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}