Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Linux Admins By James Joyner IV · · 8 min read Last reviewed Jul 2026

Linux Error Guide: 'RTNETLINK answers: File exists' — fix duplicate routes and addresses

Quick answer

Fix 'RTNETLINK answers: File exists' from ip route/addr add: understand the duplicate route or address conflict, find what already owns it, and add idempotently with replace instead of add.

  • #linux
  • #troubleshooting
  • #errors
  • #networking
Free toolkit

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

You run an ip route add or ip addr add (directly, from a network script, or from a startup unit) and the kernel rejects it because the entry it describes already exists:

RTNETLINK answers: File exists

It also surfaces when applying interface config or bringing networking up, for example:

Error: Nexthop has invalid gateway.
RTNETLINK answers: File exists
Failed to bring up eth0.

RTNETLINK is the kernel’s routing/networking configuration channel that tools like ip, ifup, NetworkManager, and systemd-networkd talk to. File exists is the netlink translation of the EEXIST errno: you asked the kernel to create a route, address, rule, or neighbor entry that duplicates one already present. The kernel will not silently overwrite it, so the add fails. The fix is to find the existing conflicting entry and either leave it alone, remove it, or use an idempotent replace instead of add.

Symptoms

  • ip route add ... or ip addr add ... fails immediately with RTNETLINK answers: File exists.
  • Bringing an interface up (ifup, systemctl restart networking, a NetworkManager dispatcher script) fails, and the log shows the same message.
  • A default route or a specific subnet route “won’t add,” yet connectivity to some destinations already works.
  • Re-running an idempotent-looking provisioning script (Ansible, a cloud-init runcmd, a boot script) fails on the second run even though it succeeded on the first.
  • Adding a secondary IP to an interface fails while the primary is already configured.

Common Root Causes

  • The route already exists. Another process, DHCP, or an earlier run already installed the same destination/gateway/metric route.
  • An overlapping route with the same key. For a given table, prefix, and metric the kernel treats it as the same entry — a duplicate default route (0.0.0.0/0) is the classic case.
  • The address is already assigned. ip addr add for an IP already on that (or another) interface returns EEXIST.
  • DHCP and static config both fighting for the same route/address, each trying to add what the other already installed.
  • A non-idempotent script re-run. The first run added the route; the second run tries add again instead of replace.
  • A leftover route from a previous interface state that was never flushed before reconfiguration.
  • Duplicate policy-routing rules or neighbor (ARP) entries added twice.

Diagnostic Workflow

Start by asking the kernel exactly what it already has for the destination you are trying to add. Do not guess — query it.

# Is this exact route already present? (checks all tables)
ip route show 203.0.113.0/24
ip route show default            # duplicate default is the most common case
ip route show table all | grep 203.0.113

If it is an address conflict, look at what owns the IP:

# Which interface already has this address?
ip addr show | grep 203.0.113.10
ip -o addr show | awk '{print $2, $4}'

See the full picture per interface and per table:

ip -br addr                      # brief address list per link
ip route show table main
ip rule show                     # policy rules (for "File exists" on ip rule add)
ip neigh show                    # neighbor/ARP entries

Check whether something else is managing the interface and racing you:

systemctl status NetworkManager systemd-networkd 2>/dev/null
journalctl -u NetworkManager -u systemd-networkd --since '10 min ago' | grep -i 'route\|address\|rtnetlink'
ps -ef | grep -E 'dhclient|dhcpcd|NetworkManager' | grep -v grep

Now choose the fix. If the existing entry is correct, do nothing — the add was redundant. If you must (re)install it, use replace, which creates-or-updates and never returns EEXIST:

# Idempotent: succeeds whether or not the entry already exists
sudo ip route replace default via 203.0.113.1 dev eth0
sudo ip addr replace 203.0.113.10/24 dev eth0

If a stale/wrong entry is in the way, delete it first, then add:

sudo ip route del 203.0.113.0/24            # remove the conflicting route
sudo ip route add 203.0.113.0/24 via 203.0.113.1 dev eth0

Example Root Cause Analysis

A team’s cloud-init runcmd added a static route to a peered VPC on first boot. After enabling a nightly re-apply of the same bootstrap script, instances started logging RTNETLINK answers: File exists and the script exited non-zero, failing the whole run.

ip route show 10.20.0.0/16 confirmed the route was already present with the exact same gateway and device — the first-boot run had installed it and it persisted. The second run blindly re-issued ip route add, which the kernel correctly rejected as a duplicate. There was no networking problem at all; connectivity to 10.20.0.0/16 worked the whole time.

The fix was a one-word change: ip route add became ip route replace, which installs the route if missing and updates it in place if present, always returning success. The script became idempotent, the nightly re-apply stopped failing, and the underlying lesson — use replace (or a “check then add”) for any route/address a script might run more than once — was applied to the rest of the provisioning code.

Prevention Best Practices

  • Use ip ... replace instead of ip ... add in scripts. replace is idempotent and immune to EEXIST, which is exactly what re-runnable automation needs.
  • Or guard the add: check with ip route show <prefix> / ip addr show | grep <ip> and only add when absent.
  • Let one system own the interface. Do not run static ip commands against an interface that NetworkManager, systemd-networkd, or DHCP is also managing — they will race and duplicate entries. Mark the interface unmanaged or configure the route in that system’s config files.
  • Flush before reconfiguring when a script rebuilds an interface’s state: ip addr flush dev eth0 / ip route flush dev eth0 (carefully) before re-adding.
  • Avoid two default routes. If you need multiple uplinks, use distinct metrics or policy routing tables, not two 0.0.0.0/0 entries in the same table.
  • Configure persistent routes in the network stack’s config (NetworkManager keyfile, netplan, /etc/network/interfaces, ifcfg route files) rather than imperative ip commands run at boot.

Quick Command Reference

# Find what already occupies the route/address/rule
ip route show <prefix>
ip route show default
ip route show table all | grep <net>
ip -br addr
ip rule show
ip neigh show

# Idempotent create-or-update (preferred in scripts)
sudo ip route replace <prefix> via <gw> dev <if>
sudo ip addr replace <ip>/<prefix> dev <if>

# Remove the conflicting entry, then add cleanly
sudo ip route del <prefix>
sudo ip route add <prefix> via <gw> dev <if>

# Who else is managing this interface?
journalctl -u NetworkManager -u systemd-networkd --since '10 min ago'
ps -ef | grep -E 'dhclient|dhcpcd' | grep -v grep

Conclusion

RTNETLINK answers: File exists is not a network fault — it is the kernel refusing to create a route, address, or rule that already exists. The vast majority of the time nothing is actually broken: a script re-ran, or DHCP already installed what you tried to add. Query the kernel for the existing entry, decide whether it is correct, and either leave it, delete-then-add, or (best) switch your add to replace so the operation is idempotent. Combined with letting a single subsystem own each interface, that eliminates the error for good.

Free download · 368-page PDF

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?

Free download · 368-page PDF

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.