From 4901a965912754a60e48b6dd8378ef870e6be16b Mon Sep 17 00:00:00 2001 From: Am-GJ Date: Sat, 11 Jul 2026 00:50:00 +0400 Subject: [PATCH] fix(reminders): sanitize ntfy Title header to ASCII (#5208) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(reminders): sanitize ntfy Title header to ASCII The ntfy notification Title header was set directly from the note title. HTTP headers must be ASCII, so a title containing emoji or other non-ASCII characters caused httpx to raise UnicodeEncodeError, which was swallowed by the surrounding try/except — so the reminder silently failed and no notification was ever sent. Sanitize the title with encode('ascii', 'replace') before placing it into the header, replacing unsupported characters with '?'. This is standard practice for HTTP header values. The note body is unaffected (it is sent as request content, not a header) and continues to support full UTF-8. * fix(reminders): also truncate ntfy title to 200 chars for header safety * style: compact ntfy header comment --------- Co-authored-by: Am-GJ Co-authored-by: RaresKeY <158580472+RaresKeY@users.noreply.github.com> --- routes/note_routes.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/routes/note_routes.py b/routes/note_routes.py index 3d356f5c9..ec8d14925 100644 --- a/routes/note_routes.py +++ b/routes/note_routes.py @@ -479,7 +479,9 @@ async def dispatch_reminder( base = intg["base_url"].rstrip("/") topic = settings.get("reminder_ntfy_topic") or "reminders" ntfy_body = synthesis or note_body or title - hdrs = {"Title": title or "Reminder", "Priority": "high", "Tags": "bell"} + # ntfy Title is an ASCII HTTP header; sanitize Unicode and cap its length. + _clean_title = (title or "Reminder").encode("ascii", "replace").decode("ascii")[:200] + hdrs = {"Title": _clean_title, "Priority": "high", "Tags": "bell"} api_key = intg.get("api_key", "") if api_key: hdrs["Authorization"] = f"Bearer {api_key}"