Milter I/O error

Your question

Hi,
I have recently set up clamav-milter with my Stalwart mail server. For the most part, everything is working perfectly fine, and emails are being processed without any issues.
However, there is one specific sender from whom I cannot receive any email. Every time they try to send a message, the connection drops immediately, and I get an os error 104 in my Stalwart logs.

2026-06-13T03:59:13Z WARN Milter I/O error (milter.io-error) listenerId = "smtp", localPort = 25, remoteIp = piv6 addr, remotePort = 34370, id = "MtaMilter with id iuqvut9iadqa", details = "Connection reset by peer (os error 104)", elapsed = 140ms

I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.

on

OS error 104 is “Connection reset by peer” on Linux. This means clamav-milter is abruptly closing the TCP connection when it processes mail from that specific sender. This is not a Stalwart bug - the reset originates on the ClamAV/milter side. Here are the most likely causes and things to check:

1. Message size limit in ClamAV
ClamAV has a MaxFileSize and MaxScanSize setting (in clamd.conf). If the email from that sender is large or contains attachments that exceed those limits, clamav-milter can close the connection. Check and raise those values if needed.

2. Protocol version mismatch
By default Stalwart negotiates milter protocol v6. Some builds of clamav-milter handle this poorly. You can try forcing protocolVersion to "v2" in your MtaMilter configuration in the WebUI (Settings > MTA > Filters > Milters):

{
  "protocolVersion": "v2"
}

3. tempFailOnError behavior
By default tempFailOnError is true, so when the I/O error occurs, Stalwart issues a 4xx temporary failure and the sending server should retry. The connection drop itself is clamav-milter terminating early - check the clamav-milter and clamd logs on your server for errors or warnings that coincide with that sender’s delivery attempts.

4. maxResponseSize
If clamav-milter is sending a response larger than Stalwart’s maxResponseSize (default 50 MB), Stalwart will drop the frame. This is less likely to be directional but worth noting.

Steps to diagnose:

  • Check /var/log/clamav/clamav-milter.log and clamd.log for errors when that sender connects.
  • Compare the message size from that sender vs. your clamd.conf scan limits.
  • Enable trace-level logging for the milter events (milter.read, milter.write) in Stalwart’s telemetry settings to see exactly where the protocol exchange breaks down.

Docs reference: Milter filters configuration

This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.

Error 104 is a connection reset: clamav-milter dropped the socket mid-scan, so the reset is coming from the milter side, not from Stalwart. Since it’s tied to one sender, their messages are most likely tripping a size limit in clamd/clamav-milter (StreamMaxLength, MaxFileSize or MaxScanSize) or causing clamd to fall over on that payload. Check the clamd log at the same timestamps and the size of that sender’s messages, and raise those limits if they’re large.

If you’d rather these messages be deferred and retried instead of failing outright, set tempFailOnError on the MtaMilter object so Stalwart returns a temporary error and the sender retries.