remotion-dev/remotion · error · Error

Render did not finish yet

Error message

Render did not finish yet

What it means

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.

Source

Thrown at packages/lambda/src/api/download-media.ts:67

		providerSpecifics: ProviderSpecifics<AwsProvider>;
		forcePathStyle: boolean;
	},
): Promise<DownloadMediaOutput> => {
	const expectedBucketOwner = await input.providerSpecifics.getAccountId({
		region: input.region,
	});
	const overallProgress = await getOverallProgressFromStorage({
		bucketName: input.bucketName,
		expectedBucketOwner,
		region: input.region,
		renderId: input.renderId,
		providerSpecifics: input.providerSpecifics,
		forcePathStyle: input.forcePathStyle,
		requestHandler: input.requestHandler,
	});

	if (!overallProgress.renderMetadata) {
		throw new Error('Render did not finish yet');
	}

	const outputPath = path.resolve(process.cwd(), input.outPath);
	RenderInternals.ensureOutputDirectory(outputPath);

	const {key, renderBucketName, customCredentials} = getExpectedOutName({
		renderMetadata: overallProgress.renderMetadata,
		bucketName: input.bucketName,
		customCredentials: input.customCredentials ?? null,
		bucketNamePrefix: REMOTION_BUCKET_PREFIX,
	});

	const {sizeInBytes} = await lambdaDownloadFileWithProgress({
		bucketName: renderBucketName,
		expectedBucketOwner,
		key,
		region: input.region,
		onProgress: input.onProgress ?? (() => undefined),

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Wait until getRenderProgress() returns a result where done is true and fatalError is false before calling downloadMedia().
  2. Verify the renderId, bucketName, and region match the values returned by renderMediaOnLambda().
  3. Check getRenderProgress() for errors — the render may have failed rather than still being in progress.
  4. Implement a polling loop around getRenderProgress() and only download once the render is confirmed complete.

Example fix

// before
await downloadMedia({
  region,
  bucketName,
  renderId,
  outPath: './out.mp4',
});

// after
let done = false;
while (!done) {
  const progress = await getRenderProgress({
    renderId,
    bucketName,
    region,
  });
  if (progress.fatalErrorEncountered) {
    throw new Error(`Render failed: ${progress.errors.join(', ')}`);
  }
  done = progress.done;
  if (!done) await new Promise((r) => setTimeout(r, 2000));
}
await downloadMedia({
  region,
  bucketName,
  renderId,
  outPath: './out.mp4',
});
Defensive patterns

Strategy: validation

Validate before calling

import {getRenderProgress} from '@remotion/lambda'; // or lambda-client in v5

async function waitForRenderDone(region, bucketName, renderId): Promise<void> {
  let done = false;
  while (!done) {
    const progress = await getRenderProgress({renderId, bucketName, region});
    if (progress.fatalErrorEncountered) {
      throw new Error(`Render failed: ${progress.errors.join('; ')}`);
    }
    done = progress.done;
    if (!done) await new Promise((r) => setTimeout(r, 2000));
  }
}

await waitForRenderDone(region, bucketName, renderId);
await downloadMedia({region, bucketName, renderId, outPath});

Type guard

import type {OverallProgress} from '@remotion/lambda';

function renderIsComplete(progress: OverallProgress): boolean {
  return Boolean(progress.renderMetadata);
}

Try / catch

try {
  await downloadMedia({region, bucketName, renderId, outPath});
} catch (err) {
  if (err instanceof Error && err.message === 'Render did not finish yet') {
    // Poll getRenderProgress() until done, then retry downloadMedia()
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12). Data as JSON: /api/errors/4f77261f36c91f05. Report an issue: GitHub.