remotion-dev/remotion · warning · ErrorWithBacktrace
Invalid matrix
Error message
Invalid matrix
What it means
Thrown by rotation_get when the computed scale of either matrix axis is zero, i.e. scale0 = hypot(matrix[0], matrix[3]) == 0 or scale1 = hypot(matrix[1], matrix[4]) == 0. A zero scale makes the rotation undefined (division by zero), so the function refuses.
Source
Thrown at packages/compositor/rust/rotation.rs:36
pub fn get_rotation(displaymatrix: &[i32]) -> Result<f64, ErrorWithBacktrace> {
let mut theta = -(rotation_get(displaymatrix))?.round();
theta -= 360.0 * (theta / 360.0 + 0.9 / 360.0).floor();
if (theta - 90.0 * (theta / 90.0).round()).abs() > 2.0 {
Err(std::io::Error::new(ErrorKind::Other, "Odd rotation angle"))?;
}
return Ok(theta);
}
pub fn rotation_get(matrix: &[i32]) -> Result<f64, ErrorWithBacktrace> {
let scale0 = (matrix[0] as f64).hypot(matrix[3] as f64);
let scale1 = (matrix[1] as f64).hypot(matrix[4] as f64);
if scale0 == 0.0 || scale1 == 0.0 {
Err(std::io::Error::new(ErrorKind::Other, "Invalid matrix"))?;
}
let rotation = (((matrix[1] as f64) / scale1).atan2((matrix[0] as f64) / scale0)) * 180.0 / PI;
return Ok(-rotation);
}
View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Strip or reset the display matrix: `ffmpeg -i in.mp4 -metadata:s:v:0 rotate= -c copy out.mp4`.
- Treat a degenerate matrix as no rotation (0 degrees) upstream instead of passing it to rotation_get.
- Re-encode the source to produce a clean display matrix.
Example fix
// before
let rot = get_rotation(&matrix)?; // throws on zero scale
// after: guard degenerate matrices upstream
let scale0 = (matrix[0] as f64).hypot(matrix[3] as f64);
let scale1 = (matrix[1] as f64).hypot(matrix[4] as f64);
let rot = if scale0 == 0.0 || scale1 == 0.0 { 0.0 } else { get_rotation(&matrix)? }; Defensive patterns
Strategy: validation
Validate before calling
let scale0 = (matrix[0] as f64).hypot(matrix[3] as f64);
let scale1 = (matrix[1] as f64).hypot(matrix[4] as f64);
if scale0 == 0.0 || scale1 == 0.0 { return 0.0; /* degenerate, treat as no rotation */ } Type guard
null
Try / catch
let rot = match rotation_get(&matrix) {
Ok(r) => r,
Err(_) => 0.0,
}; Prevention
- Sanitize display matrices: treat zero-scale as identity.
- Strip zero/placeholder rotation metadata on remux.
- Re-encode sources with clean display matrices.
When it happens
Trigger: A display matrix whose first two columns are zeroed out (degenerate/identity-gone-wrong), or partially-initialized matrix entries. The guard `scale0 == 0.0 || scale1 == 0.0` fires before the atan2 division.
Common situations: Containers writing a placeholder/zero display matrix; truncated side data parsed into i32s that happen to be zero; legacy `rotate` metadata that some muxers fill with zeros.
Related errors
- Invalid side data
- Odd rotation angle
- No audio stream found in '${input_path}'. Ensure the video c
- Not enough planes or linesizes
- Could not find audio stream in ${src}
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/bb626ab938b68705.
Report an issue: GitHub.