Troubleshooting

fail2ban configuration and regex errors

Each section below starts with an error message exactly as fail2ban prints it, so you can search this page for the text in your terminal. Each one comes with its cause and fix.

Updated 9 min readChecked against fail2ban 1.1.1

Most fail2ban configuration errors show up when you run sudo fail2ban-client -t, which tests every file and prints OK: configuration test is successful or the error and ERROR: test configuration failed. Find your message below. The most common ones are a custom failregex without <HOST> (No failure-id group in), a filter file without a [Definition] header, a misspelled filter name, and a ban action whose firewall command (nft or iptables) isn't installed. The 'allowipv6' not defined line on Debian 12 and Ubuntu 24.04 is a harmless warning, not an error.

bash
sudo fail2ban-client -t
sudo grep -E "ERROR|WARNING" /var/log/fail2ban.log | tail -20

No failure-id group in '…'#

text
ERROR   No failure-id group in '^Login failed for user \S+$'

Cause: a failregex has no way of telling fail2ban who failed. Each regex must contain <HOST>, <ADDR>, <IP4>, <IP6>, <DNS>, or a <F-ID>…</F-ID> group, either itself or through the filter's prefregex.

Fix: add the address tag where the IP appears in the log line:

/etc/fail2ban/filter.d/myapp.local
[Definition]
failregex = ^Login failed for user \S+ from <HOST>$

fail2ban-regex reports the same error immediately, so test before you reload:

bash
sudo fail2ban-regex /var/log/myapp.log /etc/fail2ban/filter.d/myapp.local

The custom filter guide explains the tags, and the regex tester checks a pattern in the browser.

No section: 'Definition'#

text
ERROR   No section: 'Definition'

Cause: a filter or action file has no [Definition] section header, or it's misspelled ([definition], [Definitions]). Section names are case-sensitive. It also happens when someone pastes failregex = … into a new .local file without any header.

Fix: every filter and action file needs the header above its options:

/etc/fail2ban/filter.d/myapp.local
[Definition]
failregex = ^Login failed for user \S+ from <HOST>$
ignoreregex =

Unable to read the filter '…'#

text
ERROR   Found no accessible config files for 'filter.d/myapp' under /etc/fail2ban
ERROR   Unable to read the filter 'myapp'
ERROR   Errors in jail 'myapp'. Skipping...

Cause: the jail names a filter that doesn't exist as /etc/fail2ban/filter.d/<name>.conf or .local. The default is filter = %(__name__)s[mode=%(mode)s], so a new jail [myapp] without a filter = line looks for filter.d/myapp.conf. Typos like nginx-http-auth.conf written in filter = (don't add the extension) cause the same thing.

Fix: check the name against ls /etc/fail2ban/filter.d/, and set filter = <name> in the jail. The matching error for actions is Unable to read action 'name'; check ls /etc/fail2ban/action.d/. The filter library lists every bundled filter.

Errors in jail '…'. Skipping...#

text
ERROR   Errors in jail 'myapp'. Skipping...

This is a summary line. The real reason is printed directly above it, usually one of the errors on this page. On a normal start fail2ban skips the broken jail and starts the others, so fail2ban-client status simply doesn't list it. fail2ban-client -t treats it as a failure.

Sorry but the jail '…' does not exist#

output
$ sudo fail2ban-client status sshdx
... ERROR   NOK: ('sshdx',)
Sorry but the jail 'sshdx' does not exist

Cause: the running server has no jail with that name. The name is misspelled, the jail isn't enabled, or it was skipped because of a config error.

Fix: list the jails that really exist with sudo fail2ban-client status. Jail names are the [section] names from jail.local, not filter file names. If the jail is missing, enable it, run sudo fail2ban-client -t, then sudo fail2ban-client reload. If it's enabled but still missing, search the log for Errors in jail.

ERROR NOK: (…)#

NOK means the server rejected a command and returned the exception text in parentheses. The part inside is the real message:

  • NOK: ("Failed to initialize any backend for Jail 'sshd'",): the backend's Python module is missing (python3-systemd for backend = systemd). See no log file / backend errors.
  • NOK: ("not banned: ['10.9.9.9']",): unbanip --report-absent for an address that isn't banned.
  • NOK: ('sshdx',): unknown jail, as above.

nft: not found or iptables: not found#

text
... -- stderr: '/bin/sh: 1: nft: not found'
... -- returned 127
... HINT on 127: "Command not found".  Make sure that all commands in ... are in the PATH of fail2ban-server process ...
... ERROR   Failed to execute ban jail 'sshd' action 'nftables' info '...': Error starting action Jail('sshd')/nftables: 'Script error'

On RHEL-family systems the shell says nft: command not found, and with iptables actions you see iptables: not found.

Cause: the ban action calls a firewall tool that isn't installed or isn't in the server's PATH. Return code 127 always means "command not found". Firewall actions start on demand, so the error appears at the first ban, not at startup. Typical cases:

  • Debian 12's fail2ban 1.0.2 defaults to iptables-multiport, but minimal installs may have only nft.
  • Newer packages default to nftables, but the nftables package was removed or never installed (some container images).

Fix: install the tool, or switch the action to the firewall you actually use:

bash
sudo apt install nftables     # or: sudo apt install iptables
/etc/fail2ban/jail.local
[DEFAULT]
banaction = nftables
banaction_allports = nftables[type=allports]

Then sudo fail2ban-client reload and test with sudo fail2ban-client set sshd banip 192.0.2.15. See ban actions for ufw, firewalld and the other choices.

Interpolation errors (%(var)s and %)#

text
'%' must be followed by '%' or '(', found: '%20'
Bad value substitution: option 'action' in section 'sshd' contains an interpolation key 'destemail' which is not a valid option name. Raw value: '...'

fail2ban's INI files use Python configparser interpolation: %(name)s inserts another option's value.

  • A literal % in a value, such as a URL-encoded string, a password or a date format in a regex, must be written as %%.
  • %(name)s pointing to nothing: the referenced option isn't defined in that section or in [DEFAULT]. Check the spelling, or define it (for example destemail = admin@example.com in [DEFAULT]).

Duplicate options and sections#

text
While reading from '/etc/fail2ban/jail.local' [line 14]: option 'bantime' in section 'sshd' already exists
While reading from '/etc/fail2ban/jail.local' [line 20]: section 'sshd' already exists

Within one file, each section may appear once and each option once per section. Merge the duplicates. Repeating a section in a different file (jail.local and jail.d/sshd.local) is fine. That's how overrides work, and the later file wins.

File contains no section headers#

text
File contains no section headers.
file: '/etc/fail2ban/jail.local', line: 1

An option sits above the first [section] line, usually from a pasted snippet. Put [DEFAULT] or the jail name above it.

Invalid filter or action definition#

text
Invalid filter definition 'sshd[mode=aggressive': unexpected option syntax

Brackets or quotes in filter = or action = are unbalanced. Arguments must look like name[key=value, key2="value with spaces"]. Multi-line action = values need each continuation line indented.

Unable to compile regular expression#

text
Unable to compile regular expression '^Failed (login from <HOST>$':
missing ), unterminated subpattern at position ...

A syntax error in a custom failregex or ignoreregex. Fix it with fail2ban-regex, which shows the same message. Note that # is not an inline comment in fail2ban config files. Only ; after whitespace starts one, so # and anything after it become part of the regex.

A regex that's valid but hangs (catastrophic backtracking)#

No error is printed. Instead fail2ban pins a CPU core and the jail stops processing lines. Nested quantifiers like (.+)+ or several .* in a row can backtrack exponentially on long lines. fail2ban 1.1.1 fixed such patterns in the bundled dovecot and domino-smtp filters (GHSA-33wh-ccjc-p397). See high CPU for how to spot and fix it.

'allowipv6' not defined in 'Definition'. Using default one: 'auto'#

text
WARNING 'allowipv6' not defined in 'Definition'. Using default one: 'auto'

This is a harmless warning, not an error. fail2ban carries on with auto, exactly as if you had set it. If fail2ban fails to start and this is just the last line you noticed, the real error is elsewhere on this page or under exit code 255.

Cause: when fail2ban reads fail2ban.conf and fail2ban.local, it looks up a fixed list of [Definition] options. allowipv6 was added in 1.0.1, but the stock fail2ban.conf only has it commented out (#allowipv6 = auto). fail2ban 1.0.1 and 1.0.2 log every missing option with a default at WARNING level, so each start, reload, fail2ban-client -t and -d prints this line, also in journalctl -u fail2ban and /var/log/fail2ban.log. From 1.1.0 on the same message is logged at DEBUG level, so it disappears after an upgrade.

fail2ban version Typical distributions Warning?
0.11.x Ubuntu 22.04, Debian 11 No (option doesn't exist)
1.0.1, 1.0.2 Debian 12, Ubuntu 24.04, EPEL 8 Yes
1.1.0, 1.1.1 Debian 13, Ubuntu 25.10/26.04, Fedora, EPEL 9/10 No (DEBUG level only)

Fix: define the option in a .local file. Don't edit fail2ban.conf, because package upgrades replace it.

bash
printf '[Definition]\nallowipv6 = auto\n' | sudo tee /etc/fail2ban/fail2ban.local
sudo fail2ban-client -t
sudo fail2ban-client reload

If fail2ban.local already exists, add allowipv6 = auto under its existing [Definition] header instead of overwriting the file. A second header in the same file causes section 'Definition' already exists. A file in /etc/fail2ban/fail2ban.d/*.local works too. The same pattern, '<option>' not defined in '<section>'. Using default one: …, applies to any option with a built-in default, and the fix is always to define it in the matching .local file. All options are on fail2ban.conf and fail2ban.local.

What allowipv6 does: it only controls whether fail2ban uses IPv6 when resolving host names: DNS names in ignoreip, host names in logs with usedns, and the server's own addresses for ignoreself. auto (default) detects IPv6 support; 1.1.0+ checks /proc/sys/net/ipv6/conf/all/disable_ipv6 first, then the interface addresses. yes/on/true/1 always resolves IPv6, no/off/false/0 resolves IPv4 only. It doesn't stop IPv6 addresses found in logs from being banned; that's up to the ban action.

FAQ#

What does "No failure-id group in" mean in fail2ban?#

Your failregex doesn't capture who failed. Every failregex needs <HOST> (or <ADDR>, <IP4>, <IP6>, <DNS>, or an <F-ID> group) at the place where the address appears in the log line. Add it, then test with fail2ban-regex before reloading.

How do I fix "No section: 'Definition'"?#

Add a [Definition] line at the top of the filter or action file, above failregex, actionban and the other options. The section name is case-sensitive. Files in filter.d/ and action.d/ always need it, including .local override files.

Why does fail2ban say the jail does not exist?#

The running server has no jail by that name. It's either misspelled, not enabled with enabled = true, or skipped because of a config error. sudo fail2ban-client status lists the jails that exist, and /var/log/fail2ban.log shows Errors in jail lines for skipped ones.

What does "returned 127" mean in fail2ban?#

Exit code 127 means a command in the action wasn't found. Usually nft, iptables, ipset, firewall-cmd, ufw, sendmail or curl isn't installed or isn't in the server's PATH. Install it or switch the jail to an action whose tools you have.

How do I check fail2ban config for errors?#

Run sudo fail2ban-client -t. It parses every configuration file, builds all enabled jails, and either prints OK: configuration test is successful or the errors followed by ERROR: test configuration failed. Run it before every reload.

Is "allowipv6 not defined in Definition" an error?#

No. fail2ban 1.0.1 and 1.0.2 print this warning because fail2ban.conf ships with the option commented out, then use the default auto and work normally. Add allowipv6 = auto under [Definition] in /etc/fail2ban/fail2ban.local to silence it. fail2ban 1.1.0 and later log it at DEBUG level only.

Spotted something wrong or out of date? Tell us — every page is checked against the current fail2ban release.