remotion-dev/remotion · error

could not cancel render %q: %w

Error message

could not cancel render %q: %w

What it means

Go client error from cancelRenderOnLambda: the final PutObject that writes the cancellation signal (renders/<renderId>/cancel.json with a cancelledAt timestamp) failed; the S3 error is wrapped with %w. The read path succeeded, so this points at write permissions, bucket state, or transport issues.

Source

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

	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)
	}

	return nil
}

// newS3Client creates an S3 client using the same shared config resolution as
// the Lambda client in invocations.go.
func newS3Client(region string, forcePathStyle bool) (*s3.Client, error) {
	awsConfig, err := config.LoadDefaultConfig(
		context.TODO(),
		config.WithRegion(region),
	)
	if err != nil {
		return nil, fmt.Errorf("could not load AWS config: %w", err)
	}
	return s3.NewFromConfig(awsConfig, func(options *s3.Options) {
		options.UsePathStyle = forcePathStyle
	}), nil

View on GitHub (pinned to 10db9de073)

Solutions

  1. Unwrap the error to the smithy APIError — AccessDenied means adding s3:PutObject on renders/* to the caller's policy.
  2. Verify the bucket still exists and the region/endpoint in the client matches the bucket's region.
  3. Retry once for transient throttling (SlowDown) with backoff.
Defensive patterns

Strategy: retry

Type guard

func isS3WriteDenied(err error) bool {
  var apiErr smithy.APIError
  return errors.As(err, &apiErr) && apiErr.ErrorCode() == "AccessDenied"
}

Try / catch

if err := client.CancelRenderOnLambda(ctx, input); err != nil {
  var apiErr smithy.APIError
  if errors.As(err, &apiErr) {
    switch apiErr.ErrorCode() {
    case "AccessDenied": // fix IAM: add s3:PutObject on renders/*
    case "SlowDown": // retry with backoff
    default: return err
    }
  }
}

Prevention

When it happens

Trigger: The caller has s3:GetObject but not s3:PutObject on the bucket; bucket deleted mid-flight; network failure during upload; wrong region endpoint for the bucket.

Common situations: IAM policies that only grant read for monitoring; least-privilege service roles missing the write statement for renders/*; S3 outage or throttling.

Related errors


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