fix(notifications): replace em dash in ntfy Title header (ASCII-only), improve error surfacing

HTTP headers are ASCII-only; the em dash in "PocketVeto — Test Notification"
caused a UnicodeEncodeError on every test attempt. Replaced with colon.

Frontend catch blocks now extract the real server error detail from the
axios response body instead of showing a generic fallback message.

Authored-By: Jack Levy
This commit is contained in:
Jack Levy
2026-03-01 12:14:37 -05:00
parent 50399adf44
commit ea52381199
2 changed files with 11 additions and 5 deletions

View File

@@ -116,7 +116,7 @@ async def test_ntfy(
return NotificationTestResult(status="error", detail="Topic URL is required") return NotificationTestResult(status="error", detail="Topic URL is required")
headers: dict[str, str] = { headers: dict[str, str] = {
"Title": "PocketVeto Test Notification", "Title": "PocketVeto: Test Notification",
"Priority": "default", "Priority": "default",
"Tags": "white_check_mark", "Tags": "white_check_mark",
} }

View File

@@ -89,8 +89,11 @@ export default function NotificationsPage() {
ntfy_password: authMethod === "basic" ? password : "", ntfy_password: authMethod === "basic" ? password : "",
}); });
setNtfyTestResult(result); setNtfyTestResult(result);
} catch { } catch (e: unknown) {
setNtfyTestResult({ status: "error", detail: "Request failed — check your topic URL" }); const detail =
(e as { response?: { data?: { detail?: string } } })?.response?.data?.detail
?? (e instanceof Error ? e.message : "Request failed");
setNtfyTestResult({ status: "error", detail });
} finally { } finally {
setNtfyTesting(false); setNtfyTesting(false);
} }
@@ -102,8 +105,11 @@ export default function NotificationsPage() {
try { try {
const result = await notificationsAPI.testRss(); const result = await notificationsAPI.testRss();
setRssTestResult(result); setRssTestResult(result);
} catch { } catch (e: unknown) {
setRssTestResult({ status: "error", detail: "Feed check failed" }); const detail =
(e as { response?: { data?: { detail?: string } } })?.response?.data?.detail
?? (e instanceof Error ? e.message : "Feed check failed");
setRssTestResult({ status: "error", detail });
} finally { } finally {
setRssTesting(false); setRssTesting(false);
} }