{"record":{"id":"d8c34a440823e16b","repo":"remotion-dev/remotion","slug":"renderer-s3-status-must-be-an-object","errorCode":null,"errorMessage":"Renderer S3 status must be an object","messagePattern":"Renderer S3 status must be an object","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/serverless-client/src/renderer-transport.ts","lineNumber":99,"sourceCode":"\t\tattempt: number;\n\t},\n\tartifactIndex: number,\n) => `${rendererTransportAttemptPrefix(options)}/artifacts/${artifactIndex}`;\n\nconst isNumber = (value: unknown): value is number =>\n\ttypeof value === 'number' && Number.isFinite(value);\n\nexport const parseS3RendererStatus = ({\n\tvalue,\n\texpectedChunk,\n\texpectedAttempt,\n}: {\n\tvalue: unknown;\n\texpectedChunk: number;\n\texpectedAttempt: number;\n}): S3RendererStatus => {\n\tif (typeof value !== 'object' || value === null) {\n\t\tthrow new Error('Renderer S3 status must be an object');\n\t}\n\n\tconst status = value as Record<string, unknown>;\n\tif (status.schema !== 1) {\n\t\tthrow new Error(\n\t\t\t`Unsupported renderer S3 status schema: ${String(status.schema)}`,\n\t\t);\n\t}\n\n\tif (status.chunk !== expectedChunk || status.attempt !== expectedAttempt) {\n\t\tthrow new Error(\n\t\t\t`Renderer S3 status identifies chunk ${String(status.chunk)}, attempt ${String(status.attempt)}; expected chunk ${expectedChunk}, attempt ${expectedAttempt}`,\n\t\t);\n\t}\n\n\tif (\n\t\ttypeof status.lambdaInvoked !== 'boolean' ||\n\t\t!isNumber(status.renderedFrames) ||","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/remotion-dev/remotion/blob/10db9de07356446fb0edb3c3ae211369b693d18b/packages/serverless-client/src/renderer-transport.ts#L81-L117","documentation":"parseS3RendererStatus() in @remotion/serverless-client strictly validates the JSON parsed from renders/{renderId}/transport/chunks/{chunk}/attempt-{attempt}/status.json before the orchestrator trusts it. First invariant: the parsed value must be a non-null object. JSON literals like null, numbers, strings, or booleans (a body of 'null', '0', 'true', '\"\"') fail here.","triggerScenarios":"status.json contains a JSON literal instead of an object - a placeholder or empty value written by an interrupted/broken uploader, or a value written by a non-Remotion process sharing the renders/ prefix.","commonSituations":"S3-compatible endpoints (MinIO and similar) returning unexpected bodies under load; stray jobs writing to the render prefix; corrupted multipart uploads of small objects.","solutions":["Download and inspect the offending object: aws s3 cp s3://<bucket>/<render-prefix>/transport/chunks/<chunk>/attempt-<n>/status.json - and confirm the body is an object literal.","Delete the render's transport prefix and retry with a fresh renderId.","Check whether any other process writes to the renders/ prefix in that bucket.","If using an S3-compatible provider, verify it returns correct object bodies under concurrent access; test against real S3 to isolate the fault."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"# Inspect the object the parser rejected before retrying\naws s3 cp \"s3://$BUCKET/renders/$RENDER_ID/transport/chunks/$CHUNK/attempt-$ATTEMPT/status.json\" - \\\n  | jq 'type'   # must print \"object\"","typeGuard":null,"tryCatchPattern":"try {\n  await renderMediaOnCloudRun({...input, renderId: makeRenderId()});\n} catch (err) {\n  if (err.message.includes('Renderer S3 status must be an object')) {\n    // corrupt/foreign status.json - sweep the prefix and retry with a fresh renderId\n    await deleteRenderFolder(bucketName, renderId);\n    await renderMediaOnCloudRun({...input, renderId: makeRenderId()});\n  } else {\n    throw err;\n  }\n}","preventionTips":["Dedicate the renders/ bucket prefix to Remotion - no other writers.","If using an S3-compatible provider, verify it returns correct object bodies under concurrent access before trusting it for renders.","Always retry with a fresh renderId after transport validation errors; the existing attempt is unrecoverable."],"tags":["serverless","s3","validation","status-json","transport"],"backgroundTag":"schema-validation-failed","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"}