{"record":{"id":"7c42a4483141ae06","repo":"remotion-dev/remotion","slug":"unexpected-jsx-attribute-character-character","errorCode":null,"errorMessage":"Unexpected JSX attribute character: ${character}","messagePattern":"Unexpected JSX attribute character: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/studio-codemods/src/print-jsx.ts","lineNumber":34,"sourceCode":"\t\t\t\treturn '&amp;';\n\t\t\tcase '\"':\n\t\t\t\treturn '&quot;';\n\t\t\tcase '<':\n\t\t\t\treturn '&lt;';\n\t\t\tcase '>':\n\t\t\t\treturn '&gt;';\n\t\t\tcase '{':\n\t\t\t\treturn '&#123;';\n\t\t\tcase '}':\n\t\t\t\treturn '&#125;';\n\t\t\tcase '\\t':\n\t\t\t\treturn '&#9;';\n\t\t\tcase '\\r':\n\t\t\t\treturn '&#13;';\n\t\t\tcase '\\n':\n\t\t\t\treturn '&#10;';\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unexpected JSX attribute character: ${character}`);\n\t\t}\n\t});\n};\n\nexport const indentInsertedJsx = ({\n\tindent,\n\tinsertion,\n}: {\n\tindent: string;\n\tinsertion: string;\n}) => {\n\treturn insertion\n\t\t.split(/\\r?\\n/)\n\t\t.map((line) => `${indent}${line}`)\n\t\t.join(insertion.includes('\\r\\n') ? '\\r\\n' : '\\n');\n};\n\nexport const printInsertedJsx = ({","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/remotion-dev/remotion/blob/46a3a6bf13ca367376ff18bbb06dae2e87e0d068/packages/studio-codemods/src/print-jsx.ts#L16-L52","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Sanitize the attribute string before calling the codemod: strip or replace control/unusual characters.","Replace the offending character with a safe equivalent (e.g. escape it yourself with a unicode escape like \\uXXXX inside the attribute value).","Trim/normalize text inputs (e.g. replace non-breaking spaces, remove \\u0000-\\u001F except tab/newline) before insertion.","If legitimate, extend the escaper's handled-character set in print-jsx.ts to cover the character."],"exampleFix":"// before -> throws on control char\nvalue = 'title\\u0007text';\n// after\nvalue = 'title\\u0007text'.replace(/[\\u0000-\\u001F\\u007F]/g, (c) => c === '\\t' || c === '\\n' ? c : ' ');","handlingStrategy":"validation","validationCode":"const sanitizeForJsxAttr = (s: string): string =>\n  s.replace(/[\\u0000-\\u001F\\u007F\\u00A0]/g, (c) =>\n    (c === '\\t' || c === '\\n' || c === '\\r') ? c : ' ');\ninsertJsxElement({attributes: {title: sanitizeForJsxAttr(userTitle)}, ...});","typeGuard":"const isJsxAttrSafe = (s: string): boolean =>\n  [...s].every((c) => c === '\\t' || c === '\\n' || c === '\\r' || (c >= ' ' && c !== '\\u007F'));","tryCatchPattern":"try {\n  insertJsxElement(opts);\n} catch (e) {\n  const m = /Unexpected JSX attribute character: (.)/.exec(e.message);\n  if (m) {\n    console.warn(`Stripping unsupported character ${JSON.stringify(m[1])}`);\n    insertJsxElement({...opts, attributes: sanitize(opts.attributes)});\n  } else throw e;\n}","preventionTips":["Sanitize all user-derived or copied text before using it in JSX attributes","Normalize whitespace (non-breaking spaces, control codes) at input boundaries","Keep attribute values plain text; escape Unicode yourself with \\uXXXX if needed"],"tags":["jsx","escaping","invalid-character"],"backgroundTag":"invalid-argument-value","analyzedSha":"46a3a6bf13ca367376ff18bbb06dae2e87e0d068","analyzedAt":"2026-09-18T00:12:20.256Z","contentChangedAt":"2026-09-18T00:12:20.256Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}