FreeBSD Troubleshooting: Common Problems and Solutions (2026)
Every FreeBSD system will eventually hit a wall -- a boot that hangs, a network interface that vanishes, a ZFS pool that goes degraded at 3 AM. This guide is a field manual for those moments. Each section gives you the diagnostic command first, then the fix. No theory, no history lessons -- just the commands you need to get the system back up.
This guide assumes FreeBSD 14.x or later. Most commands require root or sudo access.
1. Boot Failures
Boot failures are the most stressful category because you lose remote access. Knowing the recovery path before you need it is critical.
System Hangs During Boot
Diagnose: Watch the boot output. If it freezes, note the last message. Common culprits are loader.conf misconfigurations, missing kernel modules, or filesystem corruption.
Fix -- Drop to Single-User Mode:
sh# At the boot loader menu, select option 2 (Single User Mode) # Or press Escape to reach the loader prompt, then: boot -s
Once in single-user mode, you get a root shell with filesystems unmounted. Mount them:
sh# Mount root read-write mount -u / # Mount all filesystems from fstab mount -a
loader.conf Broke the Boot
If you added a bad line to /boot/loader.conf and the system will not boot:
sh# At the loader prompt (before the kernel loads), unset the offending variable: unset kern.module_that_breaks_things boot # Once booted, fix the file: vi /boot/loader.conf
If you cannot identify the bad line, bypass loader.conf entirely:
sh# At the loader prompt: set loader_conf_files="" boot
Filesystem Corruption (fsck)
Diagnose:
sh# Check filesystem status fsck -n /dev/ada0p2
Fix:
sh# For UFS filesystems, run fsck in repair mode: fsck -y /dev/ada0p2 # For ZFS, the pool auto-repairs. Force a scrub: zpool scrub zroot zpool status zroot
Boot Environment Recovery
If a system update broke things, roll back using boot environments:
sh# List available boot environments bectl list # Activate a known-good boot environment bectl activate 2026-03-15_pre-upgrade # Reboot into the working environment reboot
Boot environments are your best safety net during upgrades. See our FreeBSD boot environments guide for full setup instructions.
2. Network Problems
Interface Not Coming Up
Diagnose:
sh# List all interfaces and their status ifconfig -a # Check if the driver loaded dmesg | grep -i ethernet pciconf -lv | grep -B3 -i network
Fix:
sh# Bring the interface up manually ifconfig em0 up # Assign an IP if DHCP is not working ifconfig em0 inet 192.168.1.50 netmask 255.255.255.0 # Start DHCP client manually dhclient em0 # Make it persistent in /etc/rc.conf: sysrc ifconfig_em0="DHCP"
DNS Resolution Failures
Diagnose:
sh# Test raw connectivity (bypass DNS) ping -c 3 8.8.8.8 # Test DNS resolution drill freebsd.org # or host freebsd.org
Fix:
sh# Check resolver configuration cat /etc/resolv.conf # Set a working nameserver echo "nameserver 1.1.1.1" > /etc/resolv.conf # If using local_unbound (FreeBSD default): service local_unbound restart
Routing Issues
Diagnose:
sh# Show the routing table netstat -rn # Trace the path to a destination traceroute 8.8.8.8
Fix:
sh# Set a default gateway manually route add default 192.168.1.1 # Make it persistent sysrc defaultrouter="192.168.1.1"
PF Firewall Blocking Traffic
Diagnose:
sh# Check if PF is active pfctl -si # Show current ruleset pfctl -sr # Watch blocked packets in real time tcpdump -n -e -ttt -i pflog0
Fix:
sh# Temporarily disable PF to test if it is the cause pfctl -d # If that fixes it, find and fix the offending rule: pfctl -sr -vv | grep -i block # Reload rules after editing /etc/pf.conf pfctl -f /etc/pf.conf # Re-enable PF pfctl -e
3. Package Issues
FreeBSD's pkg is generally solid, but repository problems, lock conflicts, and broken dependencies happen. See our pkg vs ports comparison for background on the package system.
pkg Lock Conflicts
Diagnose:
sh# If you see "database is locked" errors: ls -la /var/db/pkg/local.sqlite-journal ps aux | grep pkg
Fix:
sh# Kill any stale pkg processes pkill -9 pkg # Remove stale lock file rm -f /var/db/pkg/local.sqlite-journal # Rebuild the package database if corrupted pkg update -f
Broken Dependencies
Diagnose:
sh# Check for missing dependencies pkg check -d -a # Find broken packages pkg check -B -a
Fix:
sh# Reinstall broken packages pkg install -f <package_name> # Force reinstall all packages with broken dependencies pkg check -d -a -y # Nuclear option: rebuild the entire package database pkg update -f pkg upgrade -f
Repository Errors
Diagnose:
sh# Test repository connectivity pkg update # Look for HTTP errors, certificate issues, or mirror problems
Fix:
sh# Switch to a different mirror by editing the repo config: vi /usr/local/etc/pkg/repos/FreeBSD.conf # Use the content: # FreeBSD: { # url: "pkg+http://pkg.FreeBSD.org/${ABI}/quarterly", # enabled: yes # } # Force refresh the repository catalog pkg update -f
Security Audit
Run this regularly:
sh# Check installed packages for known vulnerabilities pkg audit -F # Update the vulnerability database and audit in one step pkg audit -Fr
4. Disk and ZFS Errors
ZFS is the default filesystem on FreeBSD and it is robust, but hardware failures still happen. Our ZFS on FreeBSD guide covers the fundamentals.
Degraded ZFS Pool
Diagnose:
shzpool status # Look for DEGRADED, FAULTED, or UNAVAIL states
Fix -- Replace a Failed Disk:
sh# Identify the failed disk from zpool status output zpool status zroot # If the disk is still visible but failing: zpool replace zroot /dev/ada1 /dev/ada2 # If the disk is gone and you have a mirror or RAIDZ: zpool replace zroot ada1 ada2 # After replacement, monitor the resilver: zpool status zroot
ZFS Scrub Errors
Diagnose:
sh# Run a scrub zpool scrub zroot # Check results zpool status -v zroot # Look for "errors" line and "scan" status
Fix:
sh# If you see checksum errors on a mirrored/RAIDZ pool, ZFS auto-corrects from redundancy. # If errors persist after scrub: # Clear error counters after replacing hardware zpool clear zroot # Check SMART data on the underlying disk smartctl -a /dev/ada0
GELI Encrypted Disk Issues
Diagnose:
sh# Check GELI status geli status # List GELI providers geli list
Fix -- Unlock a GELI-Encrypted Disk:
sh# Attach the GELI provider with your key geli attach -k /root/ada1.key /dev/ada1 # If using a passphrase: geli attach /dev/ada1p2 # Mount the unlocked filesystem mount /dev/ada1p2.eli /mnt
If you lost the GELI key and have no backup, the data is unrecoverable. Always keep GELI key backups on separate media.
Disk I/O Errors
Diagnose:
sh# Check dmesg for disk errors dmesg | grep -i "error\|fault\|fail" | grep -i "ada\|da\|nvd" # Check SMART health smartctl -H /dev/ada0 smartctl -l error /dev/ada0
Fix:
If SMART reports pending sectors or reallocated sectors, plan for disk replacement immediately. Do not wait for a full failure.
5. Performance Problems
For a deep dive, see our FreeBSD performance tuning guide.
High CPU Usage
Diagnose:
sh# Real-time process view sorted by CPU top -SHP # See which processes consume the most CPU ps aux --sort=-%cpu | head -20 # Check system load averages uptime
Fix:
sh# Identify the offending process from top # If it is a runaway process: kill -TERM <pid> # If it is a legitimate process consuming too much: # Lower its priority renice 20 -p <pid> # Use cpuset to limit it to specific cores cpuset -l 0-1 -p <pid>
Memory Pressure and Swap
Diagnose:
sh# Check memory usage sysctl hw.physmem sysctl vm.stats.vm.v_free_count vmstat -h # Check swap usage swapinfo -h # See per-process memory top -o res
Fix:
sh# If swap is full, find the memory hog: ps aux --sort=-%mem | head -10 # Add emergency swap truncate -s 2G /usr/swap0 chmod 0600 /usr/swap0 mdconfig -a -t vnode -f /usr/swap0 -u 0 swapon /dev/md0 # Tune the ARC cache if ZFS is consuming too much RAM sysctl vfs.zfs.arc_max=2147483648 # Limit ARC to 2 GB # Make it persistent: echo 'vfs.zfs.arc_max="2147483648"' >> /boot/loader.conf
Disk I/O Bottlenecks
Diagnose:
sh# Real-time I/O statistics iostat -x -w 2 # Per-process I/O (requires DTrace) dtrace -n 'io:::start { printf("%s %d\n", execname, args[0]->b_bcount); }' # Check ZFS I/O zpool iostat -v zroot 2
Fix:
sh# Enable ZFS prefetch tuning sysctl vfs.zfs.prefetch.disable=0 # Increase ZFS transaction group timeout for write-heavy workloads sysctl vfs.zfs.txg.timeout=10 # Check for fragmented ZFS datasets zpool status -v zroot
For ongoing performance monitoring, set up proper tooling as described in our server monitoring guide.
6. Service Failures
Debugging rc.d Services
Diagnose:
sh# Check service status service nginx status # List all enabled services service -e # List all available services service -l # Check if the service is enabled in rc.conf sysrc -a | grep nginx
Fix:
sh# Enable and start a service sysrc nginx_enable="YES" service nginx start # If a service fails to start, run it in debug mode: service nginx onestatus # Check its rc script for debug flags: /usr/local/etc/rc.d/nginx rcvar # Many services support a config test: nginx -t
Checking Logs
Diagnose:
sh# System messages tail -100 /var/log/messages # Authentication log tail -100 /var/log/auth.log # Service-specific logs (common locations): tail -100 /var/log/nginx/error.log tail -100 /var/log/maillog tail -100 /var/log/daemon.log # Real-time log watching tail -f /var/log/messages
Permission Issues
Diagnose:
sh# Check ownership and permissions on the service's files ls -la /usr/local/etc/nginx/ ls -la /var/run/nginx.pid ls -la /var/log/nginx/ # Check if the service user exists id www
Fix:
sh# Fix ownership for a service chown -R www:www /var/log/nginx chmod 755 /var/log/nginx # If /var/run is missing the PID directory mkdir -p /var/run/nginx chown www:www /var/run/nginx
7. Kernel Panics and Crashes
Reading Crash Dumps
Diagnose:
sh# Check if crash dumps are enabled sysctl kern.dumpon # After a panic, check for dump files ls -la /var/crash/ # Read the crash dump summary cat /var/crash/info.last # Full analysis requires kernel debug symbols: kgdb /usr/lib/debug/boot/kernel/kernel.debug /var/crash/vmcore.last
Fix -- Enable Crash Dumps for Future Diagnosis:
sh# Point dumps at a swap partition or zvol sysrc dumpdev="AUTO" # Or specify a device explicitly sysrc dumpdev="/dev/ada0p3" # Enable savecore to save dumps on boot sysrc savecore_enable="YES"
Analyzing dmesg
sh# View the full kernel message buffer dmesg # Search for errors dmesg | grep -i "panic\|fatal\|error\|fail" # Save dmesg to a file for analysis dmesg > /tmp/dmesg_output.txt
DTrace for Live Debugging
DTrace is one of FreeBSD's most powerful diagnostic tools. See our DTrace tutorial for a thorough introduction.
sh# Trace system calls by process name dtrace -n 'syscall:::entry /execname == "nginx"/ { @[probefunc] = count(); }' # Trace file opens system-wide dtrace -n 'syscall::open:entry { printf("%s %s", execname, copyinstr(arg0)); }' # Watch for processes being killed dtrace -n 'proc:::exit { printf("%s (pid %d) exited with %d", execname, pid, args[0]); }'
8. Authentication Issues
Locked User Accounts
Diagnose:
sh# Check if the account is locked pw usershow <username> # Look for failed login attempts grep <username> /var/log/auth.log | tail -20
Fix:
sh# Unlock the account pw unlock <username> # Reset the password passwd <username> # If using pam_tally or similar, reset the counter # Check PAM configuration: cat /etc/pam.d/system
SSH Key Problems
Diagnose:
sh# Test SSH with verbose output ssh -vvv user@host # Check sshd logs tail -50 /var/log/auth.log | grep sshd # Check sshd configuration sshd -T | grep -i "pubkey\|authorized\|permit"
Fix:
sh# Fix permissions (SSH is strict about this) chmod 700 /home/user/.ssh chmod 600 /home/user/.ssh/authorized_keys chown -R user:user /home/user/.ssh # Ensure sshd allows key auth grep -i pubkeyauthentication /etc/ssh/sshd_config # Should be: PubkeyAuthentication yes # Restart sshd after config changes service sshd restart
sudo / doas Configuration
Diagnose:
sh# Check if the user is in the wheel group id <username> # Test sudo sudo -l -U <username>
Fix:
sh# Add user to wheel group pw groupmod wheel -m <username> # For doas, create or fix /usr/local/etc/doas.conf echo "permit :wheel" > /usr/local/etc/doas.conf chmod 600 /usr/local/etc/doas.conf # For sudo, use visudo to edit the sudoers file safely visudo # Uncomment: %wheel ALL=(ALL:ALL) ALL
9. Jail Problems
FreeBSD jails are a core feature for isolation and multi-tenancy. Our jails guide covers creation and management.
Jail Networking Issues
Diagnose:
sh# Check jail network configuration jls # From inside the jail, check the interface jexec <jail_name> ifconfig # Verify the jail can reach the network jexec <jail_name> ping -c 3 8.8.8.8
Fix:
sh# If using VNET jails, ensure the epair interface is up: ifconfig epair0a up jexec <jail_name> ifconfig epair0b up # Set DNS inside the jail echo "nameserver 1.1.1.1" > /path/to/jail/etc/resolv.conf # For NAT-based jails, check the PF rules: pfctl -sr | grep nat
Package Management Inside Jails
Diagnose:
sh# Enter the jail and check pkg status jexec <jail_name> pkg info # Check if DNS works (required for pkg) jexec <jail_name> host pkg.FreeBSD.org
Fix:
sh# Bootstrap pkg inside a new jail jexec <jail_name> pkg bootstrap -y # If pkg repos are not accessible, copy the host's resolv.conf cp /etc/resolv.conf /jails/<jail_name>/etc/resolv.conf # Update packages inside the jail jexec <jail_name> pkg update && jexec <jail_name> pkg upgrade
Jail Resource Limits
Diagnose:
sh# Check current resource limits with rctl rctl -a jail:<jail_name> # Check running jail parameters jls -j <jail_name> -v
Fix:
sh# Enable RACCT/RCTL in loader.conf (requires reboot) echo 'kern.racct.enable=1' >> /boot/loader.conf # Set memory limit for a jail rctl -a jail:<jail_name>:memoryuse:deny=2G # Set CPU percentage limit rctl -a jail:<jail_name>:pcpu:deny=50 # Make limits persistent in /etc/jail.conf or your jail manager's config
10. System Recovery
When nothing else works, you need a recovery path.
Boot Environment Rollback
This is the fastest recovery method if you use ZFS boot environments (and you should):
sh# From the loader prompt, list boot environments bectl list # Activate a previous environment bectl activate <known_good_be> reboot
See our boot environments guide for setup and best practices.
Live USB Recovery
When you cannot boot at all:
- Download a FreeBSD installation ISO and write it to USB:
sh# From another machine dd if=FreeBSD-14.2-RELEASE-amd64-memstick.img of=/dev/da0 bs=1m conv=sync
- Boot from the USB and select "Live CD" or "Shell".
- Import your ZFS pool:
sh# Discover and import the pool zpool import zpool import -f zroot # Mount the boot environment mount -t zfs zroot/ROOT/default /mnt # Now you can edit files: vi /mnt/boot/loader.conf vi /mnt/etc/rc.conf vi /mnt/etc/fstab
- Export and reboot:
shzpool export zroot reboot
Manual fsck from Live USB
For UFS systems that will not mount:
sh# From the live USB shell fsck -y /dev/ada0p2 # If the superblock is damaged, try alternate superblocks fsck -b 32 /dev/ada0p2 # After repair, mount and verify mount /dev/ada0p2 /mnt ls /mnt
Recovering a Broken rc.conf
If a bad rc.conf entry prevents boot:
sh# From single-user mode: mount -u / mount -a # Edit rc.conf vi /etc/rc.conf # Or use sysrc to remove the bad entry sysrc -x bad_variable_enable
11. Useful Diagnostic Commands
Quick reference table for the most common diagnostic commands on FreeBSD:
| Task | Command |
|---|---|
| System info | uname -a |
| Uptime and load | uptime |
| CPU usage (live) | top -SHP |
| Memory usage | vmstat -h |
| Swap usage | swapinfo -h |
| Disk space | df -h |
| ZFS pool status | zpool status |
| ZFS dataset usage | zfs list |
| Disk I/O | iostat -x -w 2 |
| Network interfaces | ifconfig -a |
| Open ports | sockstat -l |
| Routing table | netstat -rn |
| Firewall rules | pfctl -sr |
| DNS test | drill freebsd.org |
| All listening services | sockstat -4 -l |
| Kernel messages | dmesg |
| Boot messages (full) | dmesg -a |
| Hardware list | pciconf -lv |
| USB devices | usbconfig list |
| SMART disk health | smartctl -H /dev/ada0 |
| Process tree | ps auxww --forest |
| Jail list | jls |
| Boot environments | bectl list |
| Enabled services | service -e |
| Package audit | pkg audit -F |
| Check pkg deps | pkg check -d -a |
| System logs | tail -f /var/log/messages |
| Auth logs | tail -f /var/log/auth.log |
| GELI status | geli status |
| Active mounts | mount |
For monitoring these metrics over time, see our FreeBSD server monitoring guide.
12. Frequently Asked Questions
How do I recover from a bad kernel update?
Boot into the loader prompt and load the previous kernel:
shunload set kernel="kernel.old" boot
FreeBSD keeps the previous kernel as kernel.old after every upgrade. Once booted, you can use bectl to roll back the boot environment or re-run the update. See our FreeBSD update guide for the recommended update workflow.
My ZFS pool says DEGRADED but all disks are present. What do I do?
This usually means ZFS detected errors on a disk even though the disk is physically present. Run:
shzpool status -v zroot zpool scrub zroot # Wait for the scrub to complete zpool status zroot
If errors remain after scrub, check smartctl -a /dev/adaX on the affected disk. A disk can be physically present but failing. Replace it proactively. More on this in our ZFS guide.
How do I find out why a service failed to start?
Three steps:
sh# 1. Check the service status and rc script service <name> status service <name> rcvar # 2. Try starting it manually and watch stderr /usr/local/etc/rc.d/<name> onestart # 3. Check the logs tail -50 /var/log/messages tail -50 /var/log/daemon.log # Check service-specific log location from the service's config file
How do I reset the root password if I forgot it?
Boot into single-user mode (option 2 at the boot loader), then:
sh# Mount root read-write mount -u / mount -a # Reset the password passwd root # Reboot reboot
If single-user mode also requires a password (because you set kern.securelevel), you need to boot from a live USB and edit /mnt/etc/master.passwd directly, then run pwd_mkdb -p /mnt/etc/master.passwd.
Final Notes
The best troubleshooting is prevention. Keep your system updated with regular freebsd-update runs, maintain ZFS boot environments before every upgrade, monitor disk health with SMART, and keep logs rotated and readable. When something does break, work methodically: check logs first, isolate the component, test one change at a time.
For ongoing system health, combine the diagnostic commands above with a proper monitoring stack as described in our monitoring guide. For performance baselines, see our performance tuning guide. And for keeping your system current, follow our update guide.