remotion-dev/remotion · error

could not parse progress for render %q: %w

Error message

could not parse progress for render %q: %w

What it means

Go client error from cancelRenderOnLambda: the downloaded progress.json bytes could not be unmarshalled into the {CancellationEnabled bool} struct. The object at renders/<renderId>/progress.json exists but is not valid JSON or not an object (e.g. an XML error document, an empty file, or a truncated body).

Source

Thrown at packages/lambda-go/s3.go:99

	progressObject, err := client.GetObject(context.TODO(), &s3.GetObjectInput{
		Bucket: new(input.BucketName),
		Key:    new(overallProgressKey(input.RenderId)),
	})
	if err != nil {
		return fmt.Errorf("could not read progress for render %q: %w", input.RenderId, err)
	}
	defer progressObject.Body.Close()

	progressBody, err := io.ReadAll(progressObject.Body)
	if err != nil {
		return fmt.Errorf("could not read progress for render %q: %w", input.RenderId, err)
	}

	var progress struct {
		CancellationEnabled bool `json:"cancellationEnabled"`
	}
	if err := json.Unmarshal(progressBody, &progress); err != nil {
		return fmt.Errorf("could not parse progress for render %q: %w", input.RenderId, err)
	}
	if !progress.CancellationEnabled {
		return fmt.Errorf("cannot cancel render %s: the render was not started with enableCancellation: true", input.RenderId)
	}

	cancellationBody, err := json.Marshal(map[string]int64{"cancelledAt": time.Now().UnixMilli()})
	if err != nil {
		return fmt.Errorf("could not serialize cancellation signal: %w", err)
	}
	_, err = client.PutObject(context.TODO(), &s3.PutObjectInput{
		Bucket:      new(input.BucketName),
		Key:         new(cancellationKey(input.RenderId)),
		Body:        strings.NewReader(string(cancellationBody)),
		ContentType: new("application/json"),
	})
	if err != nil {
		return fmt.Errorf("could not cancel render %q: %w", input.RenderId, err)
	}

View on GitHub (pinned to 10db9de073)

Solutions

  1. Download renders/<renderId>/progress.json manually (`aws s3 cp`) and inspect its contents to see what is actually stored.
  2. Align versions: make sure the @remotion/lambda function deployed and the lambda-go client major versions match.
  3. If the render state is corrupt, abandon this renderId and start a new render with enableCancellation.
Defensive patterns

Strategy: try-catch

Validate before calling

// Sanity-check the progress payload before relying on cancellation
out, err := client.GetObject(ctx, &s3.GetObjectInput{Bucket: ptr(bucket), Key: ptr(key)})
body, _ := io.ReadAll(out.Body)
var probe map[string]any
if json.Unmarshal(body, &probe) != nil { /* corrupt state: do not cancel, alert */ }

Type guard

func isProgressJSON(body []byte) bool {
  var p struct{ CancellationEnabled bool `json:"cancellationEnabled"` }
  return json.Unmarshal(body, &p) == nil
}

Try / catch

if err := client.CancelRenderOnLambda(ctx, input); err != nil {
  if strings.Contains(err.Error(), "could not parse progress") {
    // bucket state corrupt: re-render rather than cancel
  } else { return err }
}

Prevention

When it happens

Trigger: The progress key was overwritten or corrupted; another process wrote a non-JSON payload under the same key; the render wrote with a different/older progress schema that is not a JSON object.

Common situations: Version skew between the Go client and the deployed Remotion Lambda that produced progress.json; manual tampering with the bucket layout; S3 error XML stored at the key by a buggy integration.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of remotion-dev/remotion@10db9de073 (2026-08-22). Data as JSON: /api/errors/ac47fa40f2c63c60. Report an issue: GitHub.