Template rendering issues fall into a few common patterns.
Problem: placeholder shows as literal text
Symptom: client receives a message saying "Hi {{client.first_name}}" instead of "Hi Maria."
Cause: placeholder typo. The renderer scrubs unknown placeholders before sending — if it did not, you would see the literal text in the audit log but not in the email. If a literal placeholder did go out, the audit log will show the pre-render body — check there.
Fix: open the template, check placeholder syntax (exact spelling, double curlies). Use the "Preview" button with a real client to verify.
Problem: wrong language used
Symptom: Spanish-speaking client received an English message.
Cause: the client does not have preferred_locale=es set, OR there is no Spanish template for this trigger/channel combination. The renderer falls back to tenant default in both cases.
Fix: check the client's preferred locale; check that a Spanish template exists for the trigger + channel in Templates.
Problem: expected message did not fire at all
Cause 1: notification toggle off. Check Settings → Notifications.
Cause 2: template does not exist for the channel. If you have an email template but no SMS template for invoice.reminder, only the email fires.
Cause 3: trigger genuinely did not fire. Check the audit log for the underlying event (e.g., was the visit actually completed? was the invoice actually issued?).
Problem: links in the message are broken
Cause: the URL placeholder expected the magic link or invoice pay URL but the template used wrong placeholder syntax.
Fix: use the standard placeholders: {{magic_link}}, {{invoice.pay_url}}, {{review_url}}. The system generates these automatically at render time.