What happened?
Whitespace inside a contact variable with a fallback ends up in the rendered text. With an empty firstName, the subject Hi {{ firstName, fallback= there }}, welcome! renders as Hi there , welcome!, with an extra space on each side of the fallback. {{firstName,fallback=there}} without padding renders fine.
In apps/web/src/server/utils/contact-variable-replacement.ts, CONTACT_VARIABLE_REGEX captures the fallback with fallback=([^}]+). That group swallows any spaces before }} (and after =), and replaceContactVariables returns the capture as it is. The regex already allows whitespace around the variable name and the comma, so padding inside the braces looks like it's meant to work. This helper renders campaign subjects, API-created campaign HTML and double opt-in subjects.
Replication Steps
replaceContactVariables(
'Hi {{ firstName, fallback= there }}, welcome!',
{ ...contact, firstName: null },
[],
)
// 'Hi there , welcome!' expected 'Hi there, welcome!'
Self hosted or Cloud?
Found in the code on main; not specific to either.
What happened?
Whitespace inside a contact variable with a fallback ends up in the rendered text. With an empty
firstName, the subjectHi {{ firstName, fallback= there }}, welcome!renders asHi there , welcome!, with an extra space on each side of the fallback.{{firstName,fallback=there}}without padding renders fine.In
apps/web/src/server/utils/contact-variable-replacement.ts,CONTACT_VARIABLE_REGEXcaptures the fallback withfallback=([^}]+). That group swallows any spaces before}}(and after=), andreplaceContactVariablesreturns the capture as it is. The regex already allows whitespace around the variable name and the comma, so padding inside the braces looks like it's meant to work. This helper renders campaign subjects, API-created campaign HTML and double opt-in subjects.Replication Steps
Self hosted or Cloud?
Found in the code on
main; not specific to either.