remotion-dev/remotion · error · error

error serializing inputProps. Check it has no circular refer

Error message

error serializing inputProps. Check it has no circular references or reduce the size if the object is big: %w

What it means

Returned by serializeInputProps when json.Marshal fails on the caller-supplied inputProps value. Unlike the internal-params case (1181), this is user-provided data, so the most common causes are circular references in the object graph and types Go's encoding/json cannot encode (channels, functions, complex numbers, or maps with non-string keys). The message hints at both circular references and large-object cases.

Source

Thrown at packages/lambda-go/utils.go:46

	log.Printf(
		"Warning: The props are over %dKB (%dKB) in size. Uploading them to S3 to circumvent the AWS Lambda payload size limit, which may lead to slowdown.",
		int(math.Round(float64(maxSize)/1000)), (payloadSize+1023)/1024,
	)
	return true
}

func serializeInputProps(inputProps interface{}, region string, inputType string,
	userSpecifiedBucketName string, forcePathStyle bool) (*SerializedInputProps, error) {
	if inputProps == nil {
		return &SerializedInputProps{
			Payload: "{}",
			Type:    "payload",
		}, nil
	}

	payload, err := json.Marshal(inputProps)
	if err != nil {
		return nil, fmt.Errorf("error serializing inputProps. Check it has no circular references or reduce the size if the object is big: %w", err)
	}

	if !needsUpload(len(payload), inputType) {
		return &SerializedInputProps{
			Payload: string(payload),
			Type:    "payload",
		}, nil
	}

	svc, err := newS3Client(region, forcePathStyle)
	if err != nil {
		return nil, err
	}

	bucketName := userSpecifiedBucketName
	if bucketName == "" {
		bucketName, err = getOrCreateBucket(svc, region)
		if err != nil {

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Inspect the wrapped error type: json.UnsupportedTypeError, json.MarshalerError, or 'circular references' (Go's marshaler errors out as 'cyclic data' on infinite recursion).
  2. Break cycles by passing plain DTOs into inputProps — convert ORM/component objects to simple structs first.
  3. Add `json:"-"` to fields that hold non-serializable values (channels, funcs, mutexes, loggers).
  4. If the object is legitimately large, split it: store bulk data in S3 yourself and pass a reference URL.

Example fix

// before
type props struct {
    Self  *props      // circular -> json.Marshal loops
    Log   *log.Logger // unmarshallable
}
remotion.Render(inputProps: &props{...})

// after
type props struct {
    Name string `json:"name"`
}
remotion.Render(inputProps: &props{Name: "intro"})
Defensive patterns

Strategy: type-guard

Type guard

// Reject non-serializable props before calling render.
func isJSONSafe(v interface{}) bool {
    rv := reflect.ValueOf(v)
    if !rv.IsValid() { return true }
    switch rv.Kind() {
    case reflect.Chan, reflect.Func, reflect.Complex64, reflect.Complex128:
        return false
    case reflect.Map:
        if rv.Type().Key().Kind() != reflect.String { return false }
    }
    return true
}

Try / catch

payload, err := json.Marshal(inputProps)
if err != nil {
    var te *json.UnsupportedTypeError
    if errors.As(err, &te) {
        // field of unsupported type - rebuild props as plain DTOs
    }
    return nil, err
}

Prevention

When it happens

Trigger: Passing a struct with a circular pointer graph (A points to B points back to A), a value containing a func or chan field without a json:"-" tag, a map with a struct/pointer key, or a value of type complex128.

Common situations: Passing live component objects or render context that holds back-references. Marshaling a graph built from a database ORM with bidirectional relationships. Embedding a sync.Mutex or logger inside the props struct.

Related errors


AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12). Data as JSON: /api/errors/938876d1d21f3423. Report an issue: GitHub.