remotion-dev/remotion · error · Error

Unexpected JSX attribute character

Error message

Unexpected JSX attribute character: ${character}

What it means

escapeJsxStringAttribute escapes special characters in JSX string attribute values using a per-character switch. Any character outside the explicitly handled set (quotes, tab, CR, LF, etc.) hits the default branch and throws this error naming the offending character. It is a strict allowlist rather than a generic escaper.

Solutions

  1. Sanitize the attribute string before calling the codemod: strip or replace control/unusual characters.
  2. Replace the offending character with a safe equivalent (e.g. escape it yourself with a unicode escape like \uXXXX inside the attribute value).
  3. Trim/normalize text inputs (e.g. replace non-breaking spaces, remove \u0000-\u001F except tab/newline) before insertion.
  4. If legitimate, extend the escaper's handled-character set in print-jsx.ts to cover the character.

Example fix

// before -> throws on control char
value = 'title\u0007text';
// after
value = 'title\u0007text'.replace(/[\u0000-\u001F\u007F]/g, (c) => c === '\t' || c === '\n' ? c : ' ');
Defensive patterns

Strategy: validation

Validate before calling

const sanitizeForJsxAttr = (s: string): string =>
  s.replace(/[\u0000-\u001F\u007F\u00A0]/g, (c) =>
    (c === '\t' || c === '\n' || c === '\r') ? c : ' ');
insertJsxElement({attributes: {title: sanitizeForJsxAttr(userTitle)}, ...});

Type guard

const isJsxAttrSafe = (s: string): boolean =>
  [...s].every((c) => c === '\t' || c === '\n' || c === '\r' || (c >= ' ' && c !== '\u007F'));

Try / catch

try {
  insertJsxElement(opts);
} catch (e) {
  const m = /Unexpected JSX attribute character: (.)/.exec(e.message);
  if (m) {
    console.warn(`Stripping unsupported character ${JSON.stringify(m[1])}`);
    insertJsxElement({...opts, attributes: sanitize(opts.attributes)});
  } else throw e;
}

Prevention

When it happens

Trigger: Calling escapeJsxStringAttribute (via the attributes printing path) with an attribute value containing a character not in the handled escape set — e.g. unusual control characters, non-breaking spaces treated as control chars, or unexpected Unicode in the allowed-control-character range.

Common situations: Attribute values sourced from user input or copied text containing exotic characters; capture/serialization pipelines that embed raw control codes into attribute strings; values pasted from binary or rich-text sources.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at packages/studio-codemods/src/print-jsx.ts:34

				return '&';
			case '"':
				return '"';
			case '<':
				return '&lt;';
			case '>':
				return '&gt;';
			case '{':
				return '&#123;';
			case '}':
				return '&#125;';
			case '\t':
				return '&#9;';
			case '\r':
				return '&#13;';
			case '\n':
				return '&#10;';
			default:
				throw new Error(`Unexpected JSX attribute character: ${character}`);
		}
	});
};

export const indentInsertedJsx = ({
	indent,
	insertion,
}: {
	indent: string;
	insertion: string;
}) => {
	return insertion
		.split(/\r?\n/)
		.map((line) => `${indent}${line}`)
		.join(insertion.includes('\r\n') ? '\r\n' : '\n');
};

export const printInsertedJsx = ({

View on GitHub (pinned to 46a3a6bf13)