First move, always: scan the log for severity markers¶
egrep '(warning|error|fatal|panic):' /var/log/maillog | more
The most important message is usually near the beginning of the relevant output, not the end — later errors are frequently downstream consequences of an earlier root cause, not separate problems. Postfix's severity levels mean specific things:
| Level | Meaning |
|---|---|
panic |
A bug in Postfix itself. Only a code fix resolves this; not something you can configure your way out of. |
fatal |
Missing files, wrong permissions, or a bad config setting — something you can fix, but Postfix cannot proceed until you do. |
error |
An error condition; a Postfix process will terminate itself after too many of these in a row (self-protection against a runaway failure loop). |
warning |
Non-fatal. Sometimes a real local misconfiguration worth fixing, sometimes just noise from something outside your control (a broken remote DNS server, a peer's quirky implementation) — judgment required, don't treat every warning as urgent. |
Common errors and what they actually mean¶
fatal: open database /etc/aliases.db: No such file or directory
The compiled aliases database doesn't exist yet (or a config typo is pointing somewhere wrong). Fix:
cd /etc/postfix # or wherever aliases lives on your system
newaliases # or: postalias /etc/aliases
systemctl restart postfix
Also double-check postfix_enable="YES" (BSD-style rc.conf) or the equivalent systemd enablement isn't accidentally disabled/commented out — a genuinely disabled service can produce confusingly-adjacent symptoms.
warning: /usr/local/libexec/postfix/local: bad command startup -- throttling
Frequently appears alongside the aliases.db error above rather than as an independent problem — resolving the missing-aliases-database issue often clears this at the same time.
database ... is older than source file ... (any map, not just aliases)
You edited the source file (virtual, transport, a tls_policy file, etc.) but haven't regenerated the compiled database. Fix is always the same shape:
postmap /path/to/the/file # or postalias, specifically for /etc/aliases
postfix reload
warning: request to update table btree:/var/run/smtpd_tls_session_cache in non-postfix directory /var/run
As of Postfix 2.5+, the TLS session cache must live in Postfix's own data directory; Postfix auto-redirects and just warns. Update the setting directly to silence it:
smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_scache
warning: TLS library problem: ...SSL_CTX_use_PrivateKey_file...
Almost always a stale/incorrect path in smtp_tls_key_file / smtpd_tls_key_file — commonly left pointing at an old filename after a certificate was renamed or regenerated. Confirm the path in main.cf matches what's actually on disk.
warning: TLS library problem ... enabling PIX workarounds
Not your bug — the peer mail gateway is a Cisco PIX firewall with its SMTP "fixup" feature active (historically buggy), and Postfix is logging that it detected and worked around it. Informational only.
Recipient address rejected: User unknown in local recipient table
The envelope recipient's local part doesn't correspond to any known local/virtual mailbox. Either the address genuinely doesn't exist (in which case this rejection is doing exactly its job — a sender typo shouldn't silently vanish, it should bounce clearly), or your alias/virtual-mailbox map is missing an entry it should have — check virtual_alias_maps/virtual_mailbox_maps/local_recipient_maps for the domain in question and confirm the map actually contains the address you expect.
pipe flag 'D' requires dovecot_destination_recipient_limit = 1
Specific to a Dovecot-LMTP virtual mailbox setup (see the virtual domains doc). Fix:
# /etc/postfix/main.cf
dovecot_destination_recipient_limit = 1
Host or domain name not found. Name service error for name=... type=AAAA: Host not found
Hostnames resolve fine overall, but an IPv6 (AAAA) lookup specifically is failing/timing out in a way that's confusing Postfix's resolution logic. A pragmatic fix:
smtp_host_lookup = dns, native
then restart Postfix. This tells Postfix to also consult /etc/hosts/NSS ("native" resolution) rather than relying purely on DNS, which can paper over an environment with flaky or incomplete IPv6 DNS.
Multi-host local-network relay troubleshooting¶
Specific to the "two machines on a home/local network relaying mail between each other" pattern (a home server relaying to a desktop, for example):
relay=none, ... status=deferred (connect to host[ip]:25: No route to host)
The destination firewall is blocking inbound port 25. Check/open it — e.g., historical iptables-based systems:
# /etc/sysconfig/iptables
-A INPUT -m state --state NEW -m tcp -p tcp --dport 25 -j ACCEPT
systemctl restart iptables.service
(On a modern system this is firewalld/nftables/ufw territory instead — same underlying fix, different tool: allow inbound TCP/25 from the relevant source.)
relay=none, ... status=deferred (connect to host[ip]:25: Connection refused)
Unlike "no route," this means the destination is reachable but nothing is actually listening/accepting on port 25 from that source — almost always inet_interfaces on the destination Postfix restricting which interfaces it listens on:
# was:
inet_interfaces = localhost
# change to:
inet_interfaces = all
Restart Postfix on the destination host and retest. A working delivery looks like:
postfix/smtp[...]: ...: to=<user@destination>, relay=destination[ip]:25, ..., status=sent (250 2.0.0 Ok: queued as ...)
postfix/qmgr[...]: ...: removed
General debugging workflow¶
egrep '(warning|error|fatal|panic):' /var/log/maillog— find the earliest relevant message.- Reproduce with a manual
telnet localhost 25conversation (see the installation doc) to isolate whether the problem is in Postfix's core accept/queue logic vs. something specific to the failing route/recipient. - If it's a lookup-table issue, confirm you actually re-ran
postmap/postalias/newaliasesafter the last edit — this is the most common single mistake across every category above. - If it's TLS-specific, cross-reference the TLS doc's troubleshooting section.
- If it's between two hosts you control, check both ends' logs, not just the sender's — "no route to host" and "connection refused" in particular are diagnosed on the receiving end's config/firewall, even though you'll first notice them in the sending end's deferred queue.