remotion-dev/remotion · error · InvalidArgumentException
Cannot cancel render {$renderId}: The render was not started
Error message
Cannot cancel render {$renderId}: The render was not started with enableCancellation: true. What it means
Thrown by PHPClient::cancelRenderOnLambda() (packages/lambda-php/src/PHPClient.php). Before writing the cancellation flag, the method downloads renders/{renderId}/progress.json from the render bucket and requires cancellationEnabled to be exactly true. Remotion Lambda makes cancellation opt-in (it adds overhead to the render), so only renders started with enableCancellation: true can be canceled; anything else is rejected with this InvalidArgumentException.
Source
Thrown at packages/lambda-php/src/PHPClient.php:311
$result = $this->invokeLambdaFunction($payload);
return $this->handleLambdaResponseProgress($result);
}
public function cancelRenderOnLambda(string $renderId, string $bucketName): void
{
try {
$progress = json_decode(
$this->readProgressFromS3($bucketName, "renders/{$renderId}/progress.json"),
true,
512,
JSON_THROW_ON_ERROR
);
} catch (\Throwable $exception) {
throw new Exception("Could not read progress for render {$renderId}: {$exception->getMessage()}", 0, $exception);
}
if (($progress['cancellationEnabled'] ?? false) !== true) {
throw new InvalidArgumentException(
"Cannot cancel render {$renderId}: The render was not started with enableCancellation: true."
);
}
try {
$this->writeCancellationToS3(
$bucketName,
"renders/{$renderId}/cancel.json",
json_encode(
['cancelledAt' => (int) floor(microtime(true) * 1000)],
JSON_THROW_ON_ERROR
)
);
} catch (\Throwable $exception) {
throw new Exception("Could not cancel render {$renderId}: {$exception->getMessage()}", 0, $exception);
}
}
View on GitHub (pinned to 10db9de073)
Solutions
- For any new render, opt in at render time: call $renderParams->setEnableCancellation(true) (or pass enableCancellation: true when constructing RenderParams) before renderMediaOnLambda().
- For the currently running render there is no remedy - it was not started cancellable. Let it finish, or abandon its output and start a new render with the flag enabled.
- Verify the flag took effect: download renders/{renderId}/progress.json from the render bucket and confirm cancellationEnabled is exactly true.
- If progress.json has no cancellationEnabled field at all, your deployed Remotion Lambda functions are older than the PHP client - update them (npx remotion lambda update) so client and functions match.
Example fix
// before $renderParams = new RenderParams(); // ... composition, codec, etc. - enableCancellation never set (defaults to false) $response = $client->renderMediaOnLambda($renderParams); $client->cancelRenderOnLambda($response['renderId'], $response['bucketName']); // throws // after $renderParams = new RenderParams(); $renderParams->setEnableCancellation(true); $response = $client->renderMediaOnLambda($renderParams); $client->cancelRenderOnLambda($response['renderId'], $response['bucketName']); // works
Defensive patterns
Strategy: validation
Validate before calling
// Render time - decide cancellability before starting, in one factory
$renderParams = new RenderParams();
$renderParams->setEnableCancellation(true); // required for cancelRenderOnLambda()
$response = $client->renderMediaOnLambda($renderParams);
// Cancel time - optionally verify progress.json before calling cancel
$progress = json_decode(
file_get_contents("https://{$bucketName}.s3.{$region}.amazonaws.com/renders/{$renderId}/progress.json"),
true
);
if (($progress['cancellationEnabled'] ?? false) !== true) {
// do not call cancelRenderOnLambda() - it will throw
} Try / catch
try {
$client->cancelRenderOnLambda($renderId, $bucketName);
} catch (\InvalidArgumentException $e) {
if (str_contains($e->getMessage(), 'enableCancellation')) {
// render is not cancellable - surface a clear message to the user
} else {
throw $e;
}
} Prevention
- Build all RenderParams through one factory in your codebase that sets enableCancellation(true) whenever cancellation may be needed.
- Treat cancellability as a render-time decision - it cannot be added to a running render.
- Keep a renderId-to-params mapping so you know which renders are cancellable before attempting cancel.
When it happens
Trigger: Calling $client->cancelRenderOnLambda($renderId, $bucketName) for a render started via renderMediaOnLambda() whose RenderParams left enableCancellation at its default of false (packages/lambda-php/src/RenderParams.php sets protected $enableCancellation = false), i.e. the params object was never configured with setEnableCancellation(true).
Common situations: Starting a long render and only then deciding to cancel it; passing enableCancellation into inputProps or the wrong options array instead of RenderParams; helper code copied from a template that predates the option; deployed Remotion Lambda functions older than the PHP client so progress.json never contains the field.
Related errors
- Could not read progress for render {$renderId}: {$exception-
- Could not cancel render {$renderId}: {$exception->getMessage
- Could not read progress for render {render_id}: {error}
- Cannot cancel render {render_id}: The render was not started
- Cannot cancel render #{render_id}: The render was not starte
AI-assisted analysis of remotion-dev/remotion@10db9de073 (2026-08-22).
Data as JSON: /api/errors/76121aed90cbdaf0.
Report an issue: GitHub.