You're on pfSense 2.6 (or 2.7). You add a new firewall rule, maybe to block a specific IP range or open a port. You hit Save, then Apply Changes. And bam: a red banner says The firewall rule set could not be compiled. The settings page reloads, but the new rule didn't stick. This happens more often when you've been editing aliases or interfaces just before.
What's actually going wrong
The pfSense web interface writes your rules into a file called /tmp/rules.debug. Then it runs a program called pfctl to load those rules into the kernel. pfctl is picky — it expects every alias name, every interface, every port number to be correct. If you mis-typed an alias name (like My_Alias vs MyAlias), or referenced an interface that doesn't exist anymore (like OPT3 after you removed that interface), the compile fails and the old rules stay active. The reason step 3 works is that pfctl -vnf shows you exactly which line broke.
The fix: find and kill the bad reference
Here's what to do, step by step. Don't skip any.
- Open a shell — go to Diagnostics > Command Prompt, or SSH into your box.
- Run this command:
pfctl -vnf /tmp/rules.debug 2>&1 | grep -i error
This parses the rule file and shows only the errors. You'll see something like "unknown table" or "bad interface". - Look at the line number — the error message includes a line number, like
/tmp/rules.debug:123. Write that down. - Read that line:
sed -n '123p' /tmp/rules.debug— shows you the exact rule that's broken. - Find the bad reference — if it's an alias name, go to Firewall > Aliases and check the spelling. If it's an interface, go to Interfaces > Assignments and see if the interface still exists. If you deleted an interface, any rule using it will fail.
- Fix the alias or rule — correct the name, or remove the rule referencing the dead interface. Save and Apply Changes again.
What if the error says "Table full" or "No memory"
That's different. Your alias tables are too big, or your hardware is underpowered. pfSense has a limit on how many entries an alias can have — roughly 65,000 per table. If you're blocking a huge IP range, break it into smaller subnets. Or use a URL alias that points to an external blocklist instead of typing every IP manually.
Still broken? Check these
- Check for duplicate rule numbers — rare, but if you manually edited the config.xml and messed up the row numbers, pfctl chokes. Go to Firewall > Rules, look for gaps or duplicates in the rule numbers column.
- Check for port number typos — writing
65536instead of65535will fail. pfctl doesn't accept invalid port ranges. - Check for IPv6 in an IPv4-only rule — if you have an alias that contains IPv6 addresses but the rule protocol is set to IPv4, pfctl can complain. Make sure the alias address family matches the rule.
- Restart the packet filter service — from the shell, run
pfctl -d && pfctl -e && pfctl -f /tmp/rules.debug. If the file is clean, this applies it. If it still fails, you missed a bug.
In my experience, 90% of these errors come from renaming or deleting aliases that are still referenced in rules. pfSense doesn't warn you when you remove an alias that's in use — it just lets the compile fail later. So always check your aliases first.
One more thing: if you're running pfSense on a VM with low RAM (say 512 MB), the pfctl process might OOM. Increase VM memory to at least 1 GB. You'll see "Cannot allocate memory" in the error log, not just a generic compile failure.