stamparm/maltrail · error
alert webhook POST failed
Error message
alert webhook POST failed ('%s') What it means
Maltrail's webhook alert sender POSTs the alert payload as JSON to ALERT_WEBHOOK_URL via retrieve_content. Any exception from that HTTP call is caught and logged as "alert webhook POST failed (...)"; send then returns False, so no alert is delivered through the webhook channel.
Solutions
- Verify ALERT_WEBHOOK_URL is reachable from the sensor host: curl -X POST -H 'Content-Type: application/json' -d '<payload>' $URL.
- Check DNS, proxy and firewall settings on the Maltrail host.
- Confirm the receiving webhook service is running and returns 2xx for the posted JSON.
- Inspect the logged exception text ('%s') for the exact cause (timeout vs connection refused vs HTTP status).
Example fix
# before ALERT_WEBHOOK_URL = "http://localhost:9999/hook" # nothing listening # after ALERT_WEBHOOK_URL = "https://hooks.example.com/services/xxxx" # verified with curl
Defensive patterns
Strategy: try-catch
Validate before calling
import urllib.request
try:
urllib.request.urlopen(urllib.request.Request(config.ALERT_WEBHOOK_URL, data=b'{}', headers={'Content-Type':'application/json'}), timeout=5)
except Exception as ex:
print('webhook unreachable:', ex) Type guard
def webhook_configured(cfg):
return bool(cfg.ALERT_WEBHOOK_URL) and cfg.ALERT_WEBHOOK_URL.startswith(('http://','https://')) Try / catch
try:
ok = alert.send(payload)
except Exception:
ok = False
if not ok:
fallback_log(payload) # write alert to disk/queue for replay Prevention
- Verify ALERT_WEBHOOK_URL with a test curl after every config change
- Monitor the sensor host's outbound HTTPS path (proxy, firewall, DNS)
- Point the webhook at a local relay that buffers/retries to the real service
When it happens
Trigger: The HTTP POST to config.ALERT_WEBHOOK_URL raises: DNS resolution failure, connection refused/timeout, TLS errors, or a non-2xx response raised by retrieve_content. Raised from send, which is invoked by process for each filtered log line.
Common situations: Webhook URL typo'd or pointing at a service that is down; local Slack/Mattermost relay unreachable; firewall or proxy blocking outbound HTTPS from the Maltrail host; the endpoint requiring auth headers Maltrail does not send.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- invalid 'ALERT_FORMAT
- [x] invalid IP address
- not a Maltrail provenance sidecar (bad magic)
- provenance sidecar is truncated
- packet too short for header-protection sample
AI-assisted analysis of stamparm/maltrail@77cfb06d76 (2026-09-13).
Data as JSON: /api/errors/5a3c5e259f72fba4.
Report an issue: GitHub.
Appendix: source
Thrown at core/alert.py:161
from collections import OrderedDict
return json.dumps(OrderedDict((key, event.get(key, "")) for key in
("timestamp", "sensor", "severity", "src_ip", "src_port", "dst_ip",
"dst_port", "proto", "type", "trail", "info", "reference")))
def send(event):
"""POST one event. Never raises: a webhook outage must not stop the server or the tailer."""
payload = body(event)
if payload is None:
return False
try:
retrieve_content(config.ALERT_WEBHOOK_URL, data=payload.encode(UNICODE_ENCODING),
headers={"Content-Type": "application/json"})
return True
except Exception as ex:
log_error("alert webhook POST failed ('%s')" % ex, single=True)
return False
def process(line):
"""Filter, throttle and send one log line. Returns True when a message went out."""
event = parse_event_line(line)
if event is None or not wanted(event) or throttled(event):
return False
return send(event)
def _log_path(sec=None):
localtime = time.localtime(time.time() if sec is None else sec)
return os.path.join(config.LOG_DIR, "%d-%02d-%02d.log" % (localtime.tm_year, localtime.tm_mon, localtime.tm_mday))
def _tail_once(state):View on GitHub (pinned to 77cfb06d76)