diff --git a/backend/app/services/host_silence_scan.py b/backend/app/services/host_silence_scan.py
index c104e62..d5e9c32 100644
--- a/backend/app/services/host_silence_scan.py
+++ b/backend/app/services/host_silence_scan.py
@@ -114,6 +114,13 @@ def dispatch_host_silence_notifications(db: Session, results: list[HostSilenceSc
for item in results:
if not item.created:
continue
- notify_problem(item.problem, event=None, db=db)
- sent += 1
+ try:
+ notify_problem(item.problem, event=None, db=db)
+ sent += 1
+ except Exception:
+ logger.exception(
+ "host_silence notify failed host=%s problem_id=%s",
+ item.hostname,
+ item.problem.id,
+ )
return sent
diff --git a/backend/app/services/telegram_templates.py b/backend/app/services/telegram_templates.py
index 9e4e2fb..0537453 100644
--- a/backend/app/services/telegram_templates.py
+++ b/backend/app/services/telegram_templates.py
@@ -543,8 +543,6 @@ def format_problem_telegram_html(problem: Problem, event: Event | None = None) -
msg += f"\n{html_escape(problem.title)}\n{html_escape(problem.summary)}"
if event is not None:
msg += f"\n\nТриггер: {html_escape(event.type)} ({html_escape(event.severity)})"
- elif problem.rule_id == "rule:host_silence":
- msg += "\n\nТриггер: периодическая проверка SAC (host_silence scan)"
if event.type in (
"rdp.login.success",
"rdp.login.failed",
@@ -557,4 +555,6 @@ def format_problem_telegram_html(problem: Problem, event: Event | None = None) -
"smb.admin_share.access",
):
msg += "\n" + _format_event_body_html(event)
+ elif problem.rule_id == "rule:host_silence":
+ msg += "\n\nТриггер: периодическая проверка SAC (host_silence scan)"
return append_notification_source_html(msg, generated_by="sac")
diff --git a/backend/tests/test_telegram_templates.py b/backend/tests/test_telegram_templates.py
index e17845a..342c35f 100644
--- a/backend/tests/test_telegram_templates.py
+++ b/backend/tests/test_telegram_templates.py
@@ -326,3 +326,32 @@ def test_agent_inventory_hardware_change_template():
assert "железо" in text.lower() or "Изменилось" in text
assert "memory_gb" in text
assert "32" in text
+
+
+def test_format_problem_host_silence_scan_without_event():
+ from app.models import Host, Problem
+ from app.services.problem_rules import RULE_HOST_SILENCE
+ from app.services.telegram_templates import format_problem_telegram_html
+
+ host = Host(
+ hostname="YURKOV-PC",
+ os_family="windows",
+ product="rdp-login-monitor",
+ last_seen_at=datetime(2026, 6, 11, 9, 0, tzinfo=timezone.utc),
+ )
+ problem = Problem(
+ host_id=1,
+ host=host,
+ title="Host silence: YURKOV-PC",
+ summary="Нет свежего agent.heartbeat более 300 мин",
+ severity="high",
+ status="open",
+ rule_id=RULE_HOST_SILENCE,
+ fingerprint="fp-silence",
+ event_count=0,
+ last_seen_at=datetime(2026, 6, 11, 9, 0, tzinfo=timezone.utc),
+ )
+ text = format_problem_telegram_html(problem, event=None)
+ assert "периодическая проверка SAC" in text
+ assert "host_silence scan" in text
+ assert "YURKOV-PC" in text or "UNMS" not in text # host label uses hostname