remotion-dev/remotion · error · Error

Could not locate the muted attribute

Error message

Could not locate the muted attribute

What it means

In the split-video-from-audio codemod, getMutedSourceEdit finds an existing 'muted' attribute on the <Video> element to toggle/rewrite it. If the attribute node exists but has no source location (loc is null), the codemod cannot compute the text range to replace and throws.

Solutions

  1. Run the codemod once per parse; re-parse the file between successive transforms so attributes carry fresh loc.
  2. If you added the muted attribute programmatically, serialize and re-parse before invoking the split codemod.
  3. Verify the input is parsed via recast with full location info.
  4. Guard in your pipeline: check existingMuted.loc before calling and skip with a message if absent.

Example fix

// before: attribute added in-memory, no loc
video.openingElement.attributes.push(j.mutedAttribute);
runSplitCodemod(ast);
// after: apply edit, reparse, then split
const code = applyEditsAndPrint();
runSplitCodemod(parse(code));
Defensive patterns

Strategy: type-guard

Validate before calling

const muted = element.openingElement.attributes.find((a) => getAttributeName(a) === 'muted');
if (muted && !muted.loc) { throw new Error('muted attribute lacks loc'); }

Type guard

const isLocatableAttribute = (a: t.JSXAttribute) => a.loc != null;

Try / catch

try {
  const edit = getMutedSourceEdit({element, input, getAttributeName});
} catch (err) {
  // re-parse the file and retry the codemod
}

Prevention

When it happens

Trigger: Running the codemod on a Video element that already has muted where the attribute node lacks loc — e.g. the attribute was added by a previous in-memory transform, cloned without loc, or produced by a parser that did not record locations.

Common situations: Applying the split codemod twice in one session on the same AST; codemods generated attribute nodes; files parsed with location-stripping options.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of remotion-dev/remotion@46a3a6bf13 (2026-09-18). Data as JSON: /api/errors/3717689cbca6b0ee. Report an issue: GitHub.

Appendix: source

Thrown at packages/studio-codemods/src/split-video-from-audio.ts:184

	closingFragment: {type: 'JSXClosingFragment'},
	children: [first, second],
});

const getMutedSourceEdit = ({
	element,
	input,
	prettierConfigOverride,
}: {
	element: JSXElement;
	input: string;
	prettierConfigOverride: Record<string, unknown> | null;
}): SourceEdit => {
	const existingMuted = element.openingElement.attributes.find(
		(attribute) => getAttributeName(attribute) === 'muted',
	);
	if (existingMuted) {
		if (!existingMuted.loc) {
			throw new Error('Could not locate the muted attribute');
		}

		return {
			start: recastLocToOffset(input, existingMuted.loc.start),
			end: recastLocToOffset(input, existingMuted.loc.end),
			replacement: 'muted',
		};
	}

	const {openingElement} = element;
	if (!openingElement.loc) {
		throw new Error('Could not locate the video opening element');
	}

	const openingStart = recastLocToOffset(input, openingElement.loc.start);
	const openingEnd = recastLocToOffset(input, openingElement.loc.end);
	const closingStart = openingEnd - (openingElement.selfClosing ? 2 : 1);
	const lineStart = input.lastIndexOf('\n', closingStart - 1) + 1;

View on GitHub (pinned to 46a3a6bf13)