{"record":{"id":"da3aab6daead8a9f","repo":"remotion-dev/remotion","slug":"could-not-read-progress-for-render-renderid","errorCode":null,"errorMessage":"Could not read progress for render {$renderId}: {$exception->getMessage()}","messagePattern":"Could not read progress for render (.+?): (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"packages/lambda-php/src/PHPClient.php","lineNumber":307,"sourceCode":"\n    public function getRenderProgress(string $renderId, string $bucketName, string $logLevel = \"info\", $forcePathStyle = false): GetRenderProgressResponse\n    {\n        $payload = $this->makeRenderProgressPayload($renderId, $bucketName, $logLevel, $forcePathStyle);\n        $result = $this->invokeLambdaFunction($payload);\n        return $this->handleLambdaResponseProgress($result);\n    }\n\n    public function cancelRenderOnLambda(string $renderId, string $bucketName): void\n    {\n        try {\n            $progress = json_decode(\n                $this->readProgressFromS3($bucketName, \"renders/{$renderId}/progress.json\"),\n                true,\n                512,\n                JSON_THROW_ON_ERROR\n            );\n        } catch (\\Throwable $exception) {\n            throw new Exception(\"Could not read progress for render {$renderId}: {$exception->getMessage()}\", 0, $exception);\n        }\n\n        if (($progress['cancellationEnabled'] ?? false) !== true) {\n            throw new InvalidArgumentException(\n                \"Cannot cancel render {$renderId}: The render was not started with enableCancellation: true.\"\n            );\n        }\n\n        try {\n            $this->writeCancellationToS3(\n                $bucketName,\n                \"renders/{$renderId}/cancel.json\",\n                json_encode(\n                    ['cancelledAt' => (int) floor(microtime(true) * 1000)],\n                    JSON_THROW_ON_ERROR\n                )\n            );\n        } catch (\\Throwable $exception) {","sourceCodeStart":289,"sourceCodeEnd":325,"githubUrl":"https://github.com/remotion-dev/remotion/blob/10db9de07356446fb0edb3c3ae211369b693d18b/packages/lambda-php/src/PHPClient.php#L289-L325","documentation":"PHP client error from cancelRenderOnLambda: reading and decoding renders/<renderId>/progress.json threw — the catch wraps both readProgressFromS3 (S3 get) and json_decode (JSON_THROW_ON_ERROR). So either the progress object is missing/unreadable, or its body is not valid JSON. The original exception message and chain are preserved, and the subsequent cancellationEnabled check mirrors the TS/Go clients.","triggerScenarios":"cancelRenderOnLambda($renderId) with an unknown render ID, wrong bucket, missing s3:GetObject permission, or a corrupt/non-JSON progress.json (the chained exception tells you which).","commonSituations":"Persisting render IDs across environments and cancelling against the wrong bucket; the render finished and cleanup removed progress.json; version skew between the PHP client and the deployed Lambda writing a different progress schema.","solutions":["Inspect the chained exception (getMessage of the previous Throwable) to separate 'object not found / access denied' from 'malformed JSON'.","Confirm $renderId and bucket match the values used in startRenderOnLambda / renderMediaOnLambda.","For not-found renders, treat cancellation as a no-op; for malformed JSON, verify client and deployed @remotion/lambda versions match, then re-render."],"exampleFix":"// before\n$renderId = $storedRenderId; // possibly stale\n$client->cancelRenderOnLambda($renderId, $bucket);\n\n// after: guard with getRenderProgress first, catch specific\ntry {\n    $client->cancelRenderOnLambda($renderId, $bucket);\n} catch (\\Throwable $e) {\n    if (str_contains($e->getMessage(), 'Could not read progress')) {\n        // render already gone: nothing to cancel\n        return;\n    }\n    throw $e;\n}","handlingStrategy":"try-catch","validationCode":"// Verify the render is still present before cancelling\ntry {\n    $progress = $client->getRenderProgress($renderId, $bucket);\n} catch (\\Throwable $e) {\n    // render gone: skip cancel\n}","typeGuard":null,"tryCatchPattern":"try {\n    $client->cancelRenderOnLambda($renderId, $bucket);\n} catch (Exception $e) {\n    if (str_contains($e->getMessage(), 'Could not read progress')) {\n        // missing/corrupt progress: treat render as finished or investigate $e->getPrevious()\n        return;\n    }\n    throw $e;\n}","preventionTips":["Store renderId and bucketName together at start time; cancel against the same pair.","Inspect getPrevious() to separate S3 'not found / access denied' from malformed JSON.","Keep the PHP client version aligned with the deployed Lambda version to avoid progress-schema skew."],"tags":["php","s3","cancellation","lambda"],"backgroundTag":"s3-object-not-found","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"}