remotion-dev/remotion · error · TypeError

"${name}" must be greater than -${MAX_ABSOLUTE_ANGLE} and le

Error message

"${name}" must be greater than -${MAX_ABSOLUTE_ANGLE} and less than ${MAX_ABSOLUTE_ANGLE}, but got ${JSON.stringify(value)}

What it means

The skew() effect's validateAngle helper checks that both x and y skew angles have an absolute value strictly less than MAX_ABSOLUTE_ANGLE (89 degrees). A skew angle of exactly ±89 or greater is rejected because tan() approaches infinity at ±90°, which would produce a degenerate or undefined transformation matrix.

Source

Thrown at packages/effects/src/skew.ts:100

		!Array.isArray(value) ||
		value.length !== 2 ||
		value.some((item) => typeof item !== 'number' || !Number.isFinite(item))
	) {
		throw new TypeError(`"${name}" must be a [number, number] tuple`);
	}
};

const validateUvCoordinate = (value: number, name: string): void => {
	if (value < 0 || value > 1) {
		throw new TypeError(
			`"${name}" must be between 0 and 1, but got ${JSON.stringify(value)}`,
		);
	}
};

const validateAngle = (value: number, name: string): void => {
	if (Math.abs(value) >= MAX_ABSOLUTE_ANGLE) {
		throw new TypeError(
			`"${name}" must be greater than -${MAX_ABSOLUTE_ANGLE} and less than ${MAX_ABSOLUTE_ANGLE}, but got ${JSON.stringify(value)}`,
		);
	}
};

const validateSkewParams = (params: SkewParams): void => {
	assertEffectParamsObject(params, 'Skew');
	assertOptionalFiniteNumber(params.x, 'x');
	assertOptionalFiniteNumber(params.y, 'y');
	assertOptionalUvCoordinate(params.origin, 'origin');
	const resolved = resolve(params);
	validateAngle(resolved.x, 'x');
	validateAngle(resolved.y, 'y');
	validateUvCoordinate(resolved.origin[0], 'origin[0]');
	validateUvCoordinate(resolved.origin[1], 'origin[1]');
};

const SKEW_VS = /* glsl */ `#version 300 es

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Keep both x and y skew angles strictly between -89 and 89 degrees (exclusive).
  2. If animating, clamp the interpolated value: Math.min(88, Math.max(-88, value)) or use a smaller range.
  3. Ensure you are passing degrees, not radians — the effect expects degrees and converts internally.
  4. Note the Studio schema caps at ±80, but the hard limit is ±89 — stay within ±80 for safety.

Example fix

// before — angle at exactly 89 degrees, hits the boundary
skew({ x: 89, y: 0 })
// before — angle in radians mistaken for degrees
skew({ x: 1.4, y: 0 })  // 1.4 radians ≈ 80 degrees, works but unintended

// after — safe value within the open interval (-89, 89)
skew({ x: 45, y: 0 })
// after — clamp animated values
skew({ x: Math.min(80, Math.max(-80, animatedValue)), y: 0 })
Defensive patterns

Strategy: validation

Validate before calling

// Validate and clamp skew angles to the valid range before calling skew
const MAX_SAFE_SKEW = 88; // stay below the 89-degree hard limit

function clampSkewAngle(value: number): number {
  return Math.min(MAX_SAFE_SKEW, Math.max(-MAX_SAFE_SKEW, value));
}

// Or validate strictly:
function assertValidAngle(value: number, name: string): void {
  if (Math.abs(value) >= 89) {
    throw new Error(`${name} must be strictly between -89 and 89 degrees, got ${value}`);
  }
}

assertValidAngle(rawX, 'x');
skew({ x: rawX, y: 0 });

Type guard

const isValidSkewAngle = (v: unknown): v is number =>
  typeof v === 'number' && Number.isFinite(v) && Math.abs(v) < 89;

// Usage:
const x: unknown = userInput;
if (isValidSkewAngle(x)) {
  skew({ x, y: 0 });
} else {
  // handle invalid angle
}

Try / catch

try {
  skew({ x: rawX, y: 0 });
} catch (e) {
  if (e instanceof TypeError && e.message.includes('greater than -89')) {
    // Clamp to safe range and retry
    const safeX = Math.min(80, Math.max(-80, rawX));
    skew({ x: safeX, y: 0 });
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Calling skew({ x: 89 }) (exactly at the boundary), skew({ x: 90 }) (tan(90°) is infinite), skew({ x: -89 }) (negative boundary), skew({ y: 100 }) (beyond 89°), or skew({ x: 89, y: 89 }) (both at the limit). The check is Math.abs(value) >= 89, so exactly 89 is rejected — values must be in the open interval (-89, 89).

Common situations: Animating skew angle with an interpolation that reaches or exceeds ±89; passing an angle in radians instead of degrees (e.g., 1.57 ≈ 90° but passed as if degrees); confusing the schema UI limits (±80 in Studio) with the hard-coded MAX_ABSOLUTE_ANGLE (89); extreme user-configured values from a slider or input field.

Related errors


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