remotion-dev/remotion · error · Error

Could not add effect keyframe

Error message

Could not add effect keyframe

What it means

Rejected by addEffectKeyframe in @remotion/browser-studio when `result.appliedEffectMutations[0]` is undefined after commitKeyframeMutations — the 'add' mutation targeting a specific effect on a sequence was not applied. The target is addressed by the triple (fileName, sequenceNodePath, effectIndex), so any of those being stale makes the mutation a no-op and the promise rejects.

Source

Thrown at packages/browser-studio/src/browser-studio-operations.ts:1614

						sequenceNodePath: request.sequenceNodePath,
						effectIndex: request.effectIndex,
						schema: request.schema,
						updates: [
							{
								key: request.key,
								operation: {
									type: 'add',
									frame: request.frame,
									value: JSON.parse(request.value),
								},
							},
						],
					},
				],
			});
			const mutation = result.appliedEffectMutations[0];
			if (!mutation) {
				throw new Error('Could not add effect keyframe');
			}

			return getEffectKeyframeResponse({mutation, project: result.project});
		},
		addKeyframes: async ({sequenceKeyframes, effectKeyframes}) => {
			await commitKeyframeMutations({
				label: `${sequenceKeyframes.length + effectKeyframes.length} keyframes`,
				sequenceMutations: sequenceKeyframes.map((keyframe) => ({
					fileName: keyframe.fileName,
					nodePath: keyframe.nodePath,
					schema: keyframe.schema,
					updates: [
						{
							key: keyframe.key,
							operation: {
								type: 'add',
								frame: keyframe.frame,
								value: JSON.parse(keyframe.value),

View on GitHub (pinned to b2f4e34732)

Solutions

  1. Re-resolve sequenceNodePath and the current effectIndex from the latest project state and retry
  2. Verify the effect still exists at effectIndex on the target sequence node
  3. Ensure `value` is valid JSON matching the parameter type
  4. Catch the rejection and refresh the effects panel before letting the user retry

Example fix

// before
await operations.keyframes.addEffectKeyframe({
  fileName,
  sequenceNodePath: stale,
  effectIndex: 0,
  schema: staleSchema,
  key: ' intensity',
  frame: 10,
  value: '1',
});

// after
const {nodePath, effectIndex, schema} = await resolveCurrentEffectTarget();
try {
  await operations.keyframes.addEffectKeyframe({
    fileName,
    sequenceNodePath: nodePath,
    effectIndex,
    schema,
    key: 'intensity',
    frame: 10,
    value: JSON.stringify(1),
  });
} catch {
  await refreshEffects();
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await operations.keyframes.addEffectKeyframe({fileName, sequenceNodePath, effectIndex, schema, key, frame, value});
} catch (error) {
  await refreshEffects(); // effectIndex/paths shifted
  showRetryToast();
}

Prevention

When it happens

Trigger: Calling `keyframes.addEffectKeyframe({fileName, sequenceNodePath, effectIndex, schema, key, frame, value})` where the sequence node no longer exists, the effectIndex no longer points at the intended effect (effects were added/removed/reordered), or the schema does not match the effect's parameter schema.

Common situations: Effect list changed between when the user selected an effect and clicked to keyframe it; node paths stale after an undo/redo; effectIndex computed from an older render of the timeline.

Related errors


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