{"record":{"id":"5ae295237b2dc40f","repo":"remotion-dev/remotion","slug":"cannot-cancel-render-render-id-the-render-was-n","errorCode":null,"errorMessage":"Cannot cancel render {render_id}: The render was not started with enableCancellation: true.","messagePattern":"Cannot cancel render (.+?): The render was not started with enableCancellation: true\\.","errorType":"validation","errorClass":"RemotionInvalidArgumentException","httpStatus":null,"severity":"error","filePath":"packages/lambda-python/remotion_lambda/remotionclient.py","lineNumber":645,"sourceCode":"\n        return None\n\n    def cancel_render_on_lambda(self, render_id: str, bucket_name: str) -> None:\n        \"\"\"Cancel a render started with ``enable_cancellation=True``.\"\"\"\n        s3_client = self._create_s3_client()\n        try:\n            progress_object = s3_client.get_object(\n                Bucket=bucket_name,\n                Key=f\"renders/{render_id}/progress.json\",\n            )\n            progress = json.loads(progress_object['Body'].read())\n        except (ClientError, KeyError, TypeError, json.JSONDecodeError) as error:\n            raise RemotionException(\n                f\"Could not read progress for render {render_id}: {error}\"\n            ) from error\n\n        if progress.get('cancellationEnabled') is not True:\n            raise RemotionInvalidArgumentException(\n                f\"Cannot cancel render {render_id}: The render was not started \"\n                \"with enableCancellation: true.\"\n            )\n\n        try:\n            s3_client.put_object(\n                Bucket=bucket_name,\n                Key=f\"renders/{render_id}/cancel.json\",\n                Body=json.dumps({'cancelledAt': int(time.time() * 1000)}),\n                ContentType='application/json',\n            )\n        except ClientError as error:\n            raise RemotionException(\n                f\"Could not cancel render {render_id}: {error}\"\n            ) from error\n\n    def render_still_on_lambda(\n        self, render_params: RenderStillParams","sourceCodeStart":627,"sourceCodeEnd":663,"githubUrl":"https://github.com/remotion-dev/remotion/blob/10db9de07356446fb0edb3c3ae211369b693d18b/packages/lambda-python/remotion_lambda/remotionclient.py#L627-L663","documentation":"cancel_render_on_lambda() in the Python client requires the render to have been started with enable_cancellation=True. After reading renders/{render_id}/progress.json, it checks progress.get('cancellationEnabled') and raises RemotionInvalidArgumentException when it is not True. Cancellation is opt-in in Remotion Lambda because enabling it adds overhead during rendering.","triggerScenarios":"Calling cancel_render_on_lambda() on a render whose RenderMediaParams left enable_cancellation at its default of False (packages/lambda-python/remotion_lambda/models.py: enable_cancellation: bool = False), i.e. the params object was constructed without enable_cancellation=True.","commonSituations":"Deciding to cancel only after the render started; putting enable_cancellation into input_props or a nested dict instead of the top-level RenderMediaParams field; deployed Remotion Lambda functions older than the Python client so progress.json lacks the field.","solutions":["Start cancellable renders: pass RenderMediaParams(..., enable_cancellation=True) to render_media_on_lambda().","The current non-cancellable render cannot be converted mid-flight - wait for it to finish or start a new render with the flag enabled.","Verify renders/{render_id}/progress.json contains cancellationEnabled: true shortly after the render starts.","If the field is absent from progress.json, update the deployed Remotion functions (npx remotion lambda update) to match your client version."],"exampleFix":"# before\nparams = RenderMediaParams(\n    composition=\"my-video\",\n    # enable_cancellation defaults to False\n)\nresponse = client.render_media_on_lambda(params)\nclient.cancel_render_on_lambda(response.render_id, bucket_name)  # raises\n\n# after\nparams = RenderMediaParams(\n    composition=\"my-video\",\n    enable_cancellation=True,\n)\nresponse = client.render_media_on_lambda(params)\nclient.cancel_render_on_lambda(response.render_id, bucket_name)  # works","handlingStrategy":"validation","validationCode":"# Render time - opt in once, in one place\nfrom remotion_lambda.models import RenderMediaParams\n\nparams = RenderMediaParams(\n    composition=\"my-video\",\n    enable_cancellation=True,  # required for cancel_render_on_lambda()\n)\nresponse = client.render_media_on_lambda(params)","typeGuard":null,"tryCatchPattern":"from remotion_lambda.errors import RemotionInvalidArgumentException\n\ntry:\n    client.cancel_render_on_lambda(render_id, bucket_name)\nexcept RemotionInvalidArgumentException as e:\n    if \"enableCancellation\" in str(e):\n        # render is not cancellable - report clearly, do not retry with the same params\n        pass\n    else:\n        raise","preventionTips":["Create RenderMediaParams through one helper that always sets enable_cancellation=True if your workflow ever cancels.","Remember cancellation is opt-in per render - it cannot be enabled after the render starts.","Check progress.json for cancellationEnabled during development to confirm the flag serializes correctly."],"tags":["lambda","cancellation","python","opt-in","progress-json"],"backgroundTag":"opt-in-flag-required","analyzedSha":"10db9de07356446fb0edb3c3ae211369b693d18b","analyzedAt":"2026-08-22T21:45:17.748Z","contentChangedAt":"2026-08-22T21:45:17.748Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}