Linux Error Guide: 'Network is unreachable' — Fix Missing Routes and Default Gateway
Resolve 'Network is unreachable' ENETUNREACH on Linux by checking interface state, default route, gateway reachability, and network manager configuration.
- #linux
- #troubleshooting
- #errors
- #networking
Stuck on this Linux Admins error? Get the free incident triage checklist
A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.
Overview
Network is unreachable (POSIX error code ENETUNREACH) is returned by the kernel when a connect(), sendto(), or bind() syscall targets a destination for which the routing table contains no usable path. The error surfaces from any network tool:
ping: connect: Network is unreachable
curl: (7) Failed to connect to 10.0.0.5 port 443: Network is unreachable
The key characteristic is that the error appears immediately — there is no timeout, no SYN wait, no ARP exchange. The kernel rejects the call locally before any packet leaves the machine because it cannot determine which interface and gateway to use. This distinguishes it from No route to host (EHOSTUNREACH), where the routing table does contain an applicable route but the next-hop or destination host is itself unreachable — a useful distinction covered briefly in the Diagnostic Workflow section below.
Common scenarios where this error appears: a freshly provisioned VM where DHCP did not finish configuring an interface; a host with a statically assigned IP where the default gateway was never written to the config; an interface that is physically down or administratively disabled; or a route that was manually deleted and not restored.
Symptoms
- All outbound connections to external addresses fail immediately with the error text.
ping 8.8.8.8fails butping 127.0.0.1succeeds (loopback works; external routing does not).ssh,curl,wget, andncall fail to connect to remote addresses.- The error message appears with no perceptible delay — there is no waiting for a timeout.
ip route showproduces empty output or lacks adefaultline.- Existing established connections (if any) may continue to function briefly if they were formed before the route was lost.
Common Root Causes
- No default gateway — the routing table has no
default(0.0.0.0/0) entry, so the kernel has no path for traffic not covered by a more specific route. - Interface administratively down — the interface is in the DOWN state; the kernel will not route traffic through it.
- NO-CARRIER — the interface is up in software but the physical link is absent (unplugged cable, detached VM NIC, network adapter in error state).
- DHCP failure — DHCP was expected to configure IP and gateway but timed out, leaving the interface unconfigured.
- Static IP without a default route — an IP address was assigned manually but no
ip route add defaultwas run and no gateway was written to the persistent config. - IPv6-only default route — the routing table has a default route in the IPv6 table (
ip -6 route show) but not in IPv4, and the destination address is IPv4. - Manually deleted route — an administrator or a network management daemon removed the default route and it has not been restored.
Diagnostic Workflow
Start by listing all interfaces and their IP addresses:
ip addr show
Look for the expected interface (commonly eth0, ens3, ens5, or enp0s3). Confirm it has an IPv4 address assigned (a inet line under the interface). Also note the state flags in the first line of each interface block.
Check for DOWN or NO-CARRIER conditions:
ip link show
An interface that is administratively down will show state DOWN. An interface that is up in software but has no physical link shows NO-CARRIER in the flags. Both conditions prevent routing.
Bring a DOWN interface up:
sudo ip link set dev eth0 up
Inspect the routing table:
ip route show
A working host should have at least one default line:
default via 10.0.0.1 dev eth0 proto dhcp src 10.0.0.42 metric 100
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.42
If there is no default line, the error is caused by a missing default route. Test what route the kernel would choose for a specific destination:
ip route get 8.8.8.8
If this prints ENETUNREACH or an error, the kernel has confirmed no route exists.
Add a temporary default route to restore connectivity immediately (replace 10.0.0.1 and eth0 with your actual gateway and interface):
sudo ip route add default via 10.0.0.1 dev eth0
Verify connectivity by pinging the gateway first, then an external address:
ping -c 3 10.0.0.1 # gateway reachability
ping -c 3 8.8.8.8 # external routing
Distinguish from ‘No route to host’: if ip route get <destination> returns a valid route but traffic still fails, the problem is not a missing route — it is EHOSTUNREACH, meaning the next-hop or destination host is refusing or not responding. That condition is a separate issue involving firewall rules, routing loops, or a host that is genuinely down.
Check NetworkManager if it manages the interface:
nmcli device status
nmcli connection show
A device in the disconnected state means NetworkManager has not applied a connection profile to it. Use nmcli device connect eth0 to trigger re-connection, or inspect and apply the correct connection:
nmcli connection up "<connection-name>"
Check systemd-networkd if that is the active network daemon:
systemctl status systemd-networkd
networkctl status eth0
For IPv6-specific routing problems, check the IPv6 table separately:
ip -6 route show
ip -6 route get 2001:4860:4860::8888
If the IPv6 table has a default route but the IPv4 table does not, and the application targets an IPv4 address, the IPv4 routing failure causes the error.
Inspect the static network configuration files to understand the persistent state:
# Netplan (Ubuntu 18.04+)
cat /etc/netplan/*.yaml
# systemd-networkd
cat /etc/systemd/network/*.network
# legacy ifupdown
cat /etc/network/interfaces
Example Root Cause Analysis
A newly provisioned Ubuntu 22.04 cloud VM has two NICs: eth0 (management, configured by DHCP) and eth1 (data plane, static IP applied manually). After the static IP is set on eth1, attempts to reach addresses in the data-plane subnet fail with the error.
Check the interface state:
ip addr show eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 52:54:00:ab:cd:ef brd ff:ff:ff:ff:ff:ff
inet 192.168.10.20/24 brd 192.168.10.255 scope global eth1
The IP is assigned and the interface is UP. Check the routing table:
ip route show
default via 10.0.0.1 dev eth0 proto dhcp src 10.0.0.42 metric 100
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.42
192.168.10.0/24 dev eth1 proto kernel scope link src 192.168.10.20
There is a link-scope route for the 192.168.10.0/24 subnet, so local subnet traffic works. But attempts to reach hosts outside that subnet via eth1 (through the data-plane gateway 192.168.10.1) fail because no route for those destinations exists. Add the specific route:
sudo ip route add 172.16.0.0/16 via 192.168.10.1 dev eth1
Then persist it by adding a routes block to the netplan config:
# /etc/netplan/01-eth1.yaml
network:
version: 2
ethernets:
eth1:
addresses:
- 192.168.10.20/24
routes:
- to: 172.16.0.0/16
via: 192.168.10.1
sudo netplan apply
Connectivity to the target range is now restored and will survive reboots.
Prevention Best Practices
- Use a network management daemon (NetworkManager or systemd-networkd) rather than manually calling
ip route. Manual routes do not survive reboots; management daemons restore them automatically from config files. - Validate netplan changes before applying with
netplan try, which applies the config temporarily and reverts it after 120 seconds unless you confirm — preventing accidental lockout on remote systems. - Test connectivity after every network config change before closing the session, including
pingto both the gateway and an external address. - Monitor the default route in your metrics or monitoring system. Prometheus
node_exporterdoes not expose routing table state natively, but a simple shell probe (ip route get 8.8.8.8 > /dev/null 2>&1) can be wrapped in a custom exporter or a systemd service health check. - Write static routes to config files immediately — never rely on in-memory
ip route addcommands that disappear at reboot. - Check for NO-CARRIER after VM migrations or NIC hotplug by running
ip link showimmediately after the event.
Quick Command Reference
# List all interfaces and their IPs
ip addr show
# Check interface state (UP, DOWN, NO-CARRIER)
ip link show
# Bring a down interface up
sudo ip link set dev eth0 up
# Show routing table
ip route show
# Test route for a specific destination
ip route get 8.8.8.8
# Add a temporary default route
sudo ip route add default via <gateway-ip> dev <interface>
# Delete a misconfigured default route
sudo ip route del default
# Ping the gateway (from your routing table)
ping -c 3 <gateway-ip>
# NetworkManager: show device and connection state
nmcli device status
nmcli connection show
# NetworkManager: bring up a connection
nmcli connection up "<connection-name>"
# systemd-networkd: check interface status
networkctl status eth0
# IPv6 routing table
ip -6 route show
ip -6 route get 2001:4860:4860::8888
# Validate and apply netplan config safely
sudo netplan try
sudo netplan apply
Conclusion
Network is unreachable always has a local cause — the kernel refused to route the packet because it found no applicable entry in the routing table. The diagnostic path is straightforward: check that the interface is UP and has an IP address, check that the routing table contains a default route or a route covering the destination, and verify the gateway is reachable. If ip route show has no default line, adding one with ip route add default via <gw> dev <iface> will restore outbound connectivity immediately. The follow-up step is always to write that route into the persistent network configuration so it survives reboots — whether through netplan, systemd-networkd .network files, or a NetworkManager connection profile.
Fixed it? Get 500 Linux Admins & DevOps AI prompts — free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.
Did this fix your issue?
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.