Fixing Duplicate OSPF Router ID: Flapping Neighbors and Dead Timers

Flapping OSPF adjacencies usually come down to a duplicate router ID or an expiring dead timer. Real CML captures on IOS XE 17.18.2 show the neighbor-table tell, the fix, and why the duplicate-router-ID log never fired.

OSPF neighbor table listing the same router ID 1.1.1.1 twice on two different interfaces

An OSPF adjacency that will not stay up is worse than one that never comes up at all. A neighbor stuck in INIT is at least honest about it. A flapping one keeps tearing down and rebuilding, so the whole area re-floods LSAs and re-runs SPF, routes drop out of the table and come back, and syslog fills with %OSPF-5-ADJCHG messages that all look identical.

Two causes account for most of it. The first is a duplicate router ID: two routers claiming the same 32-bit identifier, each originating a Router-LSA with that ID, so SPF is computing a topology that does not exist. The second is dead timer expiry, where hellos stop arriving inside the dead interval and the adjacency is torn down on a loop. This article covers both, with the duplicate case captured live. If you want the wider picture first, the OSPF configuration and troubleshooting guides cover how adjacencies are supposed to form before you start pulling one apart.

Everything below came off a three-router CML lab (R1 to R2 to R3, iol-xe on IOS XE 17.18.2, one area 0) captured on 2026-07-20. R1 and R3 were deliberately given the same router ID, 1.1.1.1, with R2 as the common neighbor. One result was not what the textbooks promise, and it changes the advice.

What a Flapping Adjacency Looks Like

The signature of a flap is a pair of %OSPF-5-ADJCHG messages repeating on a cycle. One takes the neighbor down, one brings it back. Both of these are real lines logged on R2:

*OSPF-5-ADJCHG: Process 1, Nbr 1.1.1.1 on Ethernet0/1 from FULL to DOWN, Neighbor Down: Dead timer expired
*OSPF-5-ADJCHG: Process 1, Nbr 3.3.3.3 on Ethernet0/1 from LOADING to FULL, Loading Done

Read the tail of each line, not the head. Neighbor Down: Dead timer expired means hellos stopped arriving for the length of the dead interval. LOADING to FULL, Loading Done is the healthy end of a rebuild. Those two alternating for the same neighbor is a flap. A different down reason (interface down, an explicit clear, MTU) is a different problem, and the meaning of each OSPF neighbor state is the refresher for that.

A flap logged on one side only usually means unidirectional hello loss rather than a shared fault. And an adjacency that never reaches FULL is not flapping, it is failing to build (see why an OSPF adjacency never forms at all).

How Duplicates Happen

1. Copy/Paste Configs

Most common cause: clone a router config without changing the router ID.

! Original router
router ospf 1
 router-id 10.0.0.1

! Cloned router (forgot to change!)
router ospf 1
 router-id 10.0.0.1  <-- DUPLICATE

This one bites in production because the clone behaves perfectly on the bench, where it has no OSPF neighbors, and only misbehaves once it is cabled in.

2. Automatic Selection Picks the Same IP

If you never configure router-id, OSPF picks one: the highest loopback address if a loopback is up, otherwise the highest active physical interface address. Two routers can reach the same answer.

R1: Lo0 = 192.168.1.1 (Router ID auto-selected)
R2: Lo0 = 192.168.1.1 (Router ID auto-selected)  <-- DUPLICATE

Duplicate loopbacks sound like something nobody would do, right up until you inherit a network where every branch standby carries the same management loopback. The selection rules are in how a Cisco router chooses its OSPF router ID.

3. VM and Template Cloning

Same failure as copy/paste, at scale, and usually automated so it hits twenty devices at once. A golden-image workflow needs the router ID as a per-device variable, not part of the image.

Detecting Duplicate Router IDs

The Neighbor Table Is the Clearest Tell

Run show ip ospf neighbor on the router sitting between the two suspects and read the Neighbor ID column. Here is R2 with the break in place:

R2# show ip ospf neighbor
Neighbor ID     Pri   State           Dead Time   Address         Interface
1.1.1.1           1   FULL/BDR        00:00:38    10.0.23.1       Ethernet0/1      <-- this is R3 (rid forced to 1.1.1.1)
1.1.1.1           1   FULL/BDR        00:00:38    10.0.12.1       Ethernet0/0      <-- this is R1

The same Neighbor ID appears twice, through two different addresses on two different interfaces. A router ID identifies exactly one router, so one ID arriving from two directions means two devices are claiming it. Both R1 and R3 originate a Router-LSA with ID 1.1.1.1, and SPF across the area now believes there is one node carrying both sets of links.

Check Syslog, but Do Not Rely on It

The message everyone hunts for is %OSPF-4-DUP_RTRID_NBR (older docs cite %OSPF-4-DUP_RTRID1):

show logging | include DUP_RTRID

The honest lab result: on IOS XE 17.18.2 that log never fired, with two neighbors plainly sharing 1.1.1.1. An empty grep is not proof of a unique router ID, so check the neighbor table as well. And if you want ADJCHG and DUP_RTRID messages somewhere you can read them after the fact, set up remote logging on IOS XE before you need it.

Check the OSPF Database

show ip ospf database router 1.1.1.1

A duplicated ID produces a single LSA that each router keeps overwriting with a higher sequence number. The link list changes between reads and the sequence climbs far faster than the 30-minute refresh explains. A Router-LSA whose sequence number is racing is a duplicate until proven otherwise.

Check the Local Router ID

show ip ospf | include ID

This reports the ID the process is actually running, which is not necessarily the one in the config if somebody set router-id without clearing the process.

Finding Which Router Has the Duplicate

Challenge: nothing tells you which two routers are fighting over the ID. The log message, when it fires at all, names the ID and not the offenders.

Method 1: Read the Address and Interface Columns

Fastest method, straight out of the capture above. The Neighbor ID column is poisoned, but Address and Interface are not: they come from the IP header and the receiving port. In the lab, 10.0.23.1 on Ethernet0/1 is R3 and 10.0.12.1 on Ethernet0/0 is R1. Two addresses, one claimed ID, and you know exactly which two boxes to log into.

Method 2: Check Every Router

If the duplicate is not adjacent to a single common neighbor, fall back to brute force:

show ip ospf | include ID
show run | include router-id

The first gives the running ID, the second the configured one. A mismatch is worth noting on its own.

Method 3: Use CDP or LLDP

If you know the link but not the hostname behind it:

show cdp neighbors Ethernet0/1 detail
show lldp neighbors Ethernet0/1 detail

Match the local interface against the one from the neighbor table and you have the far-end hostname and management address.

Fixing Duplicate Router IDs

Step 1: Identify Both Routers

Use one of the three methods above. Fixing the wrong device just moves the conflict.

Step 2: Decide Which Router to Change

Best practice: change the router ID on the device added later. The original ID is already throughout the LSDB, referenced by every other router's SPF tree, and probably in your monitoring too. In the lab R3 was the newcomer, so R3 moved to 3.3.3.3.

Step 3: Change the Router ID

R3(config)# router ospf 1
R3(config-router)#  router-id 3.3.3.3
*OSPF-6-NEW_RTRID: New router-id will take effect immediately. If OSPF adjacencies are UP ... they will be reset.
R3# clear ip ospf process   [yes]

Note the wording of %OSPF-6-NEW_RTRID. It warns that adjacencies will be reset, but the new ID is not in use yet. The router is telling you what will happen, not what just did.

Step 4: Clear the OSPF Process

The change does not take effect until the process restarts. Two ways to do that.

Option 1: clear the process

clear ip ospf process
Reset ALL OSPF processes? [no]: yes

Impact: every adjacency on that router drops and reforms. Seconds of reconvergence on a small area, longer on a large one.

Option 2: reload the router

reload

Impact: full outage, and almost never worth it for a router ID change.

Recommendation: use clear ip ospf process in a maintenance window, and note the confirm prompt defaults to no. Pressing enter twice does nothing, which is a mercy the first time you fat-finger it and a trap the first time you assume it worked.

Step 5: Verify

Here is what R2 logged as the fix landed. The stale 1.1.1.1 adjacency did not vanish the instant R3 restarted, it sat there until the dead timer ran out:

*OSPF-5-ADJCHG: Process 1, Nbr 1.1.1.1 on Ethernet0/1 from FULL to DOWN, Neighbor Down: Dead timer expired
*OSPF-5-ADJCHG: Process 1, Nbr 3.3.3.3 on Ethernet0/1 from LOADING to FULL, Loading Done

Then the neighbor table, which is the actual proof:

R2# show ip ospf neighbor
Neighbor ID     Pri   State           Dead Time   Address         Interface
3.3.3.3           1   FULL/BDR        00:00:39    10.0.23.1       Ethernet0/1
1.1.1.1           1   FULL/BDR        00:00:32    10.0.12.1       Ethernet0/0

Two distinct Neighbor IDs, both FULL. Sample it three or four times over a couple of minutes: if the Dead Time column keeps resetting rather than counting toward zero, the adjacency is stable. That plus a clean show logging | include ADJCHG is the verification. Then confirm the routes landed, because a correct LSDB and a correct routing table are not the same thing - see why an OSPF route is in the database but not the routing table.

The Other Cause of Flapping: Dead Timer Expiry

The Neighbor Down: Dead timer expired line above appeared for a benign reason (a stale adjacency aging out), but it is the identical message you get when hellos genuinely stop. If that is what your logs show and every router ID is unique, the duplicate hunt is over and you are looking at one of these.

Hello / dead timer mismatch
TellTimers differ per side
Checkshow ip ospf interface
Lossy or congested link
TellInput errors climbing
Checkshow interfaces counters
One-way hello
TellOne side INIT, one FULL
CheckACL, multicast, mask
MTU mismatch
TellStuck in EXSTART
Checkip mtu on both ends

Rule out the timer mismatch first, because it is deterministic. Both ends must agree on the hello and dead intervals, so if you tuned one side for faster convergence and forgot the other, the adjacency builds and dies on a predictable cycle. Compare with show ip ospf interface Ethernet0/1 | include Hello|Dead. Why the dead interval is four times the hello is covered in how OSPF hello and dead intervals work together.

If the timers agree, look at the link. Hellos are small and unacknowledged, so a link only has to drop a handful in a row to blow the dead interval. Rising input errors, CRCs or late collisions point at a physical fault, and a duplex mismatch producing interface errors is the classic version: the link stays up, ping mostly works, and only the protocols with tight timers notice.

The last two cases present differently enough to be their own articles. A neighbor that reaches INIT on one side and never gets further is a one-way hello problem, not a flap. A neighbor cycling through EXSTART without reaching FULL is almost always an MTU mismatch stalling the database exchange, since DBD packets are large enough to hit the smaller MTU while the tiny hellos sail through.

Preventing Duplicate Router IDs

1. Always Configure the Router ID Manually

Do not rely on automatic selection. It is stable right up until somebody adds a loopback or an interface bounces.

router ospf 1
 router-id 10.255.255.1

2. Use a Consistent Numbering Scheme

Pick a block that exists only for router IDs and overlaps nothing routable:

  • R1: 10.255.255.1
  • R2: 10.255.255.2
  • R3: 10.255.255.3

Document it in your IPAM or on the diagram. A scheme that lives only in somebody's head is a duplicate waiting to be typed.

3. Back the Router ID with a Loopback

interface loopback 0
 ip address 10.255.255.1 255.255.255.255
 description OSPF Router ID

router ospf 1
 router-id 10.255.255.1

Configuring router-id explicitly is what makes it deterministic. Matching it to a real loopback is what makes it useful, because the ID in the LSDB is then an address you can ping and SSH to.

4. Check Configs Before Deployment

show run | include router-id

Compare against the documented scheme before the device is cabled in. Five seconds now, or a maintenance window and a process clear later.

5. Treat the Router ID as a Template Variable

If you clone configs: clone, immediately change the router ID, verify, then connect to the network. In any templating system the router ID belongs in the per-device variable file, never in the shared template body.

Impact of Duplicate Router IDs

On the two offenders: both originate a Router-LSA under the same ID, each overwriting the other with a higher sequence number, so the LSDB never settles. On every other router in the area: conflicting LSAs for what they believe is one node, and SPF runs against whichever version arrived last, so routes appear, disappear and return pointing at different next hops.

Network-wide that means suboptimal paths, transient loops, blackholed traffic, and intermittent connectivity that will not reproduce on demand. Those symptoms point investigators at the application rather than the routing protocol, which is how duplicates survive for months.

What This Was Captured On

Three routers in Cisco Modeling Labs: R1 to R2 to R3, all iol-xe on IOS XE 17.18.2, everything in area 0. R1 holds router ID 1.1.1.1 on Ethernet0/0 (10.0.12.1), R2 is the common neighbor at 2.2.2.2 (Ethernet0/0 10.0.12.2, Ethernet0/1 10.0.23.2), and R3 was forced to 1.1.1.1 on Ethernet0/0 (10.0.23.1) to create the break. An EEM applet on R3 set router-id 3.3.3.3 and answered the clear prompt, while a second applet ran show ip ospf neighbor on R2 into syslog so both tables were captured verbatim. Driving a device with an EEM applet is a reliable way to time a break and its fix without a human in the loop.

Gotchas From the Lab

The duplicate did not flap. On IOS XE 17.18.2 the two adjacencies sharing a router ID coexisted, both at FULL/BDR, sampled repeatedly over several minutes. Most guides describe continuous flapping. Here the adjacencies were rock solid while the LSDB underneath them was wrong. Do not use adjacency stability as evidence that your router IDs are unique.

%OSPF-4-DUP_RTRID_NBR never fired. The log everyone tells you to grep for did not appear in this topology. It is a real message and it does fire elsewhere, but an empty log is not a clean bill of health. Check both signals.

The stale adjacency outlives the fix. When R3 restarted with the new ID, R2 held the old 1.1.1.1 entry until the dead timer expired, so for up to a full dead interval the table still showed the problem you just fixed. Verify too fast and you will think the change failed.

The confirm prompt defaults to no. clear ip ospf process asks "Reset ALL OSPF processes? [no]:" and a bare enter declines. Somebody runs it, sees no disruption, and concludes the change took effect. It did not.

The same logic transfers to EIGRP, which has its own router ID and its own duplicate mess (dropped external routes rather than a corrupted LSDB). Chasing an EIGRP adjacency that will not stabilise follows the same shape: read the table, identify the peer by address, fix the newcomer.

Key Takeaways

  • The neighbor table is the primary diagnostic. The same Neighbor ID on two interfaces and two addresses is a duplicate. That tell was reliable in the lab when the log was not.
  • Do not trust adjacency stability. On IOS XE 17.18.2 the duplicated adjacencies stayed FULL. A duplicate can corrupt the LSDB without ever flapping a neighbor.
  • Identify the offenders by Address and Interface, not by router ID. Those columns come from the packet and the port.
  • The change needs a process clear. Setting router-id only arms it, the confirm prompt defaults to no, and the far side holds the stale entry until the dead timer expires.
  • Dead timer expiry is the other main flap cause. Same log line, different fix: match the timers, then look for packet loss on the link.
  • Prevent it in the template. Configure the router ID explicitly from a documented block, kept as a per-device variable.

Duplicate router IDs, one-way hellos and MTU mismatches are the three failures behind most broken OSPF adjacencies, and each has a different tell in show ip ospf neighbor. The rest of the OSPF troubleshooting series works through them with lab captures:

Neighbor stuck in INIT, one side only
Hellos arriving in one direction only, and the ACL, mask and multicast causes behind it.
Neighbor stuck in EXSTART or EXCHANGE
Why a DBD packet stalls the database exchange when the two ends disagree on MTU.
Neighbor never appears at all
Area, network type, authentication and subnet checks for an adjacency that never starts.
Setting the router ID properly
Selection order, loopbacks, and making the value deterministic before it bites you.
Route is in the LSDB but not the routing table
The next problem once your adjacencies are stable and the database is finally clean.

Read next