Guide

Spanning Tree Loop: Find the Storm and the Wrong Root

A switch with pegged CPU, every port in the VLAN busy at once and one MAC address relearned on a different port over and over is not a problem you diagnose — it is one you stop. A network that forwards fine but takes thirty seconds to recover a failed uplink is the opposite: nothing is looping, and the answer is mode, priority or port roles. Treating the two as one is why spanning-tree troubleshooting goes badly. This guide splits them at the first step, then works the commands that name the root, show what is blocking, and separate the faults that let a redundant link forward. For the protocol underneath, see what Spanning Tree Protocol is.

Triage first: a loop, or a tree you do not like?

Before any command, decide which family you are in. An active loop is an emergency with a fixed first move — contain it. A network that works but converges slowly, or fails over badly, is a design problem you can take your time over. The commands overlap; the order does not.

Getting it wrong costs you either way. show spanning-tree on a switch drowning in a storm gives a console that will not echo and output you cannot trust. Pulling cables from a network that merely has the wrong root creates the outage you were called about.

The spanning tree hub covers the protocol in design order. This page is the order you use when something is already broken.

What you observeActive loop — contain it nowNo loop — a convergence or design fault
Switch CPUPegged, and the console echoes slowly or not at allNormal
Interface loadEvery port in the VLAN busy at once, including ports that normally carry almost nothingTraffic sits where you expect it
MAC address tableOne address is relearned on a different port repeatedly, and the switch keeps saying soStable
ReachabilityHosts drop out in groups, ARP fails, management sessions dieHosts reach each other; only failover is slow
When it startedRight after a cable move, a port change or a new switchIt has always behaved this way
First moveBreak the redundant path by hand, then diagnoseNothing urgent. Read the tree.

If it is a loop, break the path before you read anything

A broadcast storm floods the switch's own control plane, so SSH usually fails and the console is what you have left. Do not start by rebooting: the switch comes back with the same configuration and the loop comes back with it.

Shut one port in the redundant path by hand. The best candidate is whatever changed most recently — the port someone patched this morning, or the interface whose config was edited. This is not a fix; it is how you get a CLI that answers. Write down which port you shut: if the storm stops, the loop ran through it and you have halved the search.

If no switch answers, break the path physically at the patch panel, or in a virtual lab shut the interface from whichever node still responds. Storm control caps the damage rather than removing the loop — do not mistake a quiet network for a correct one.

SW2# configure terminal
SW2(config)# interface Ethernet0/2
SW2(config-if)# shutdown
SW2(config-if)# end
SW2# show processes cpu | include five seconds
SW2# show mac address-table count

Breaking the redundant path by hand. This diagnoses nothing — it buys back a usable CLI.

Name the root, then compare it with the design

show spanning-tree vlan 10 settles who is root. Compare the Address under Root ID with the Address under Bridge ID: if they match, this switch is root and IOS prints a line saying so. If they differ, the root is elsewhere and the Port line names the interface pointing at it.

Read the Root ID priority as arithmetic. The default bridge priority is 32768, IOS adds the VLAN ID on top as the extended system ID, and the configured value must be a multiple of 4096. So a Root ID priority of 32778 for VLAN 10 is 32768 plus 10: the default, untouched, everywhere. When every switch carries the default the lowest MAC wins. That is not an elected root, it is an accident.

Per-VLAN spanning tree makes "the root" a per-VLAN answer. show spanning-tree root prints one line per VLAN with the root ID, the cost to it and the root port — the fastest way to spot a VLAN whose tree moved while its neighbors stayed put. Run it on every switch: one switch's view cannot draw the tree.

  • Root ID address equals Bridge ID address — this switch is root for that VLAN.
  • Root ID priority ending in the VLAN number with a 32768 base — nobody set a priority anywhere.
  • A different root per VLAN when the design says one root — a priority set for some VLANs and not others, or a trunk that does not carry every VLAN.
  • Root reached through an access-layer switch — the tree is inverted and traffic takes a long way round.
SW2# show spanning-tree vlan 10

VLAN0010
  Spanning tree enabled protocol rstp
  Root ID    Priority    32778
             Address     aabb.cc00.0100
             Cost        100
             Port        2 (Ethernet0/1)
             Hello Time  2 sec  Max Age 20 sec  Forward Delay 15 sec

  Bridge ID  Priority    32778  (priority 32768 sys-id-ext 10)
             Address     aabb.cc00.0300
             Hello Time  2 sec  Max Age 20 sec  Forward Delay 15 sec
             Aging Time  300 sec

Interface           Role Sts Cost      Prio.Nbr Type
------------------- ---- --- --------- -------- --------------------
Et0/1               Root FWD 100       128.2    P2p
Et0/2               Altn BLK 100       128.3    P2p

Illustrative output, not a capture. Both priorities read 32778 — the 32768 default plus VLAN 10 — so this root won on MAC address alone.

Find out whether anything is blocking at all

A loop exists when a redundant physical path has no logical block on it. That is countable, so count it. Three switches in a triangle have one loop, so one port must block for each VLAN crossing all three trunks. show spanning-tree blockedports lists every VLAN in one screen, but only the ports blocked on the switch you run it on, and its trailing count is port-VLAN pairs. The block for a VLAN sits on one switch, so run it on all three and add the counts — two VLANs should total two.

show spanning-tree summary gives the same answer from the other direction: the mode, whether the switch is root for anything, and a per-VLAN row counting ports in each state. Zero in the Blocking column is normal on the root and on any switch off the loop; what you are hunting is a VLAN no switch in the domain blocks at all.

Then read the roles in show spanning-tree vlan 10 on every switch. Root is the single port aimed at the root bridge, Desg forwards for its segment, Altn blocks a redundant path toward the root, and Back backs up a designated port on the same segment. Your redundant links must show as Altn and BLK somewhere; if they do not, one switch is not hearing another's BPDUs.

One trap before you call the tree broken: a link that is down is not a blocked port. An err-disabled trunk turns a triangle into a V, and a V has no loop to block, so the tree looks innocent while your redundancy is gone. Check show interfaces status err-disabled and show spanning-tree inconsistentports before trusting a clean list.

SW2# show spanning-tree blockedports

Name                 Blocked Interfaces List
-------------------- ------------------------------------
VLAN0010             Et0/2
VLAN0020             Et0/2

Number of blocked ports (segments) in the system : 2

SW2# show spanning-tree summary
Switch is in rapid-pvst mode
Root bridge for: none
<output omitted>

Name                   Blocking Listening Learning Forwarding STP Active
---------------------- -------- --------- -------- ---------- ----------
VLAN0010                      1         0        0          1          2
VLAN0020                      1         0        0          1          2

Illustrative output, not a capture. A healthy triangle carrying two VLANs, read on the one switch that holds both blocks — its two neighbors correctly report zero.

Each ends with the same result — a path with no block on it — and each is found with a different command. Work them in order: the first two are far more common and take seconds to rule out.

1. A port that should block was made an edge port

PortFast tells a port it has an end host on it and no loop is possible, so it forwards without waiting for spanning tree to decide. On an access port that is correct. On a switch-to-switch trunk it is the problem itself: the port forwards before the topology is known.

show spanning-tree interface Ethernet0/1 detail reports the edge or PortFast status. Check every inter-switch link, not just the suspect one. The global spanning-tree portfast default arms access ports only, so an edge trunk almost always means an explicit spanning-tree portfast trunk, or a port that was an access port when the line was written and later became a trunk.

Remove it from the trunk and keep it on the access ports. no spanning-tree portfast trunk takes the flag off the interface; reach for the spanning-tree portfast disable form where a global default would otherwise turn PortFast on, because that is the case IOS keeps in the config.

SW3(config)# interface Ethernet0/1
SW3(config-if)# no spanning-tree portfast trunk
SW3(config-if)# spanning-tree portfast disable
SW3(config-if)# end
SW3# show spanning-tree interface Ethernet0/1 detail

Taking the edge flag off a trunk. Verify on both ends — one side is enough to cause the loop.

2. BPDU guard is missing at the edge

A PortFast access port with no BPDU guard accepts a switch as happily as a PC. Somebody plugs a desk switch into two wall ports, or daisy-chains one back into the same VLAN, and the loop arrives through a port nobody thinks of as a trunk.

BPDU guard shuts that down at the first BPDU: the port goes err-disabled instead of joining the topology. Arm it globally with spanning-tree portfast bpduguard default, which applies only to PortFast ports, or per interface with spanning-tree bpduguard enable. The port stays down until you bounce it or configure automatic recovery — an unexplained port down is cheaper than a campus outage.

When a port does err-disable, read the reason before clearing it. show interfaces status err-disabled names the cause, and a BPDU-guard reason on an access port means something sending BPDUs was plugged in there.

A link that carries frames in one direction only produces a loop with no configuration error anywhere. The end that stops hearing BPDUs ages out the information it was blocking on and moves the port to forwarding; the other end never knew anything changed and keeps forwarding too.

Loop guard matches this failure. A loop-guard port that stops receiving BPDUs moves to loop-inconsistent rather than forwarding, so the safe outcome — a blocked port — is what happens when information goes missing. Enable it with spanning-tree guard loop on non-edge ports or spanning-tree loopguard default globally, and check with show spanning-tree inconsistentports.

UDLD attacks the same fault a layer lower by exchanging identity messages with the neighbor, which is why it belongs on fiber, where a strand or transceiver can fail one-way. Be honest about what a virtual lab shows here: a hypervisor link does not fail in one direction, so this is a cause you reason about and design against rather than reproduce.

4. A PVST or native VLAN inconsistency

Per-VLAN spanning tree sends one BPDU per VLAN across a trunk, tagged for that VLAN, except the native VLAN's, which goes untagged. A trunk whose ends disagree about the native VLAN therefore puts each switch's untagged BPDUs into the wrong VLAN on the other side. IOS blocks the affected VLANs on the port and logs a port-VLAN-ID inconsistency — protection that looks like an unexplained block until you know the message.

The related fault is a VLAN allowed on one end of a trunk and pruned on the other. The pruned end neither sends nor accepts that VLAN, BPDUs included, so the far end hears nothing and unblocks its redundant port for that VLAN alone. Nothing loops: the frames it forwards die at the pruned end. You lose that VLAN on that link, while every other VLAN on the same trunks is fine.

show interfaces trunk on both ends is the whole diagnosis: mode, native VLAN, allowed list and the VLANs actually forwarding. Compare the two outputs line by line rather than reading one and assuming. show spanning-tree inconsistentports names the ports already blocked for inconsistency.

A misconfigured EtherChannel is the same family. When one side bundles its links and the other treats them as independent ports, spanning tree sees a different number of links on each end and can leave one forwarding — see EtherChannel with LACP, and check show etherchannel summary on both ends whenever a bundle is in the loop.

5. A switch that never saw a BPDU

The last family is a switch with no information at all, which forwards everywhere because it believes there is nothing to block. BPDU filter is the usual cause. On an interface it stops BPDUs in both directions unconditionally — a loop waiting for someone to cable it. Set globally as spanning-tree portfast bpdufilter default it applies only to PortFast ports and stops filtering the moment a BPDU arrives, which is far safer but still needs a reason.

Spanning tree disabled for a VLAN does the same more bluntly — the VLAN has no tree, so every trunk carrying it forwards. show spanning-tree summary lists the VLANs actually active, and a VLAN missing from that list is the answer.

Mode mismatch belongs here in its milder form. Rapid-PVST and PVST+ interoperate, the rapid end falling back to classic behavior on that link, so this costs convergence time rather than causing a loop. Catch it anyway: a switch nobody migrated is a switch nobody is managing.

Not a loop: slow convergence and bad failover

If nothing is flooding and hosts reach each other, you are in the second family: the fault is timing or topology, not a loop. Four checks cover nearly all of it.

Start with the mode, and read it rather than assume it. PVST+ — a per-VLAN version of classic 802.1D — walks a port through listening and learning on the standard 15-second forward delay, so a link takes tens of seconds to recover. Rapid-PVST replaces that with a proposal and agreement handshake and converges in well under a second. Which one a switch comes up in depends on platform and image: older Catalyst switches ship in PVST+, current CML switch images boot in Rapid-PVST. The first line of show spanning-tree summary is the only answer that counts, and one switch left in PVST+ drags its own links back to 802.1D timing whatever the rest of the domain runs. Configuring Rapid Spanning Tree covers the migration.

Then check the edge ports. A host port without PortFast spends tens of seconds in listening and learning every time the PC boots, long enough for DHCP to give up — the machine takes a self-assigned address and the ticket says "no network", not "slow spanning tree".

Third, the link type. The rapid handshake runs only on point-to-point links, and IOS infers that from duplex: full is point-to-point, half is shared, and a shared link falls back to the slow transition. Modern inter-switch links negotiate full duplex, so this is a confirmation unless duplex was hard-set.

Fourth, the path itself. If the root was chosen by MAC address, traffic crosses the campus through whichever switch happened to win. Fix that with bridge priority on the switch you want, not by tuning cost on individual ports — cost steers one link, priority places the root. Leave the hello, max-age and forward-delay timers alone; a topology that genuinely needs different ones gets them set on the root bridge, which propagates them.

Close it out so it cannot come back

A repaired tree still held together by default priorities breaks again the next time a switch is replaced. Four settings turn the topology from an accident into a decision.

Place the root deliberately, on the distribution or core switch most traffic already crosses, and give a second switch the next-lowest priority as standby. The root primary macro sets 24576, or 4096 below the current root if something already sits at or under that; root secondary sets 28672. Read back what it wrote. Do it for every VLAN those switches carry, not just the one you were troubleshooting.

Then protect the decision. Root guard on ports facing downstream switches drops a port into root-inconsistent state if a superior BPDU arrives, so a switch plugged in below you cannot take the root away. Loop guard covers the missing-BPDU case on the other non-edge ports: the two are mutually exclusive on a port, and the interface setting beats the global loop guard default. PortFast and BPDU guard cover the edge — set both through the global defaults, so a new access port is protected without anyone remembering to type anything.

Finally, re-enable the port you shut during containment and confirm the topology settles the way you now intend. The spanning tree cheat sheet has the verification commands.

SW1(config)# spanning-tree mode rapid-pvst
SW1(config)# spanning-tree vlan 10,20 root primary
SW2(config)# spanning-tree vlan 10,20 root secondary

SW1(config)# spanning-tree portfast default
SW1(config)# spanning-tree portfast bpduguard default
SW1(config)# spanning-tree loopguard default
SW1(config)# errdisable recovery cause bpduguard
SW1(config)# errdisable recovery interval 300

SW1(config)# interface Ethernet0/1
SW1(config-if)# spanning-tree guard root

The hardening set, written as configuration. Apply the global lines on every switch in the domain and root guard only on ports facing downstream switches.

Verify the repair on both families

Whichever family you were in, the same readings say you are done, and you take them on every switch rather than the one you edited. Added up across the domain, the counts must agree with the cabling: two loops means two blocked ports per VLAN, and one loop with nothing blocking anywhere means you have not finished.

  1. show spanning-tree summary — the mode is what you intended and every VLAN you carry is listed as active.
  2. show spanning-tree root — the same root ID appears on every switch for every VLAN, and it is the switch you chose.
  3. show spanning-tree blockedports — the count is per switch, so add it up across the domain: the total must equal the redundant paths times the VLANs crossing them. One switch reporting zero is normal; the whole domain reporting zero is not.
  4. show spanning-tree inconsistentports — empty. A port listed here is blocked by root guard, loop guard or a PVID mismatch, each a separate fault to close.
  5. show interfaces status err-disabled — empty, or every entry explained. Then ping across the VLAN and watch the MAC address table stay still.

Frequently asked questions

How do I tell a broadcast storm from a busy network?

A storm loads every port in the VLAN at once, including ports that normally carry almost nothing, and the switch CPU climbs with it. The tell that settles it is the MAC address table: in a loop the same source address is relearned on a different port over and over, and the switch reports those moves repeatedly. Ordinary congestion is heavy on the ports you would expect and leaves the MAC table stable.

Which switch should be the root bridge?

Choose it, do not let it happen. Pick the distribution or core switch that most traffic already crosses, give it the lowest bridge priority for every VLAN it carries, and give a second switch the next lowest as a standby. Default priority everywhere means the election falls to the lowest MAC address, which takes no account of where a switch sits and can send traffic the long way round.

Does PortFast cause loops?

Only where it does not belong. On a port with a single end host, PortFast is correct and saves tens of seconds every time the host boots. On a switch-to-switch link it tells the port to forward before spanning tree has decided whether it should, which is exactly the condition a loop needs. Pair PortFast with BPDU guard on every access port so a switch appearing on one of them shuts the port instead of reshaping the topology.

Why is no port blocking in my triangle?

First check you are reading the whole triangle rather than one switch: the block for a VLAN lands on a single switch, so the other two reporting nothing blocked is the healthy answer. If no switch in the triangle blocks, then either spanning tree is not running for that VLAN, one switch never hears the others because of a BPDU filter or a trunk mismatch, or a link in the triangle is already down so there is no longer a loop to block. Check the mode and the active VLAN list in show spanning-tree summary, compare native VLAN and allowed VLANs on both ends of every trunk, and look for an err-disabled interface before deciding the tree is wrong.

Should I use storm control to fix a loop?

No. Storm control caps how much broadcast, multicast or unknown unicast a port will pass, so it limits the damage a loop does without removing the loop. It is worth keeping on access ports as a backstop, but the topology is still wrong and the loop is still there. Fix the root placement, the blocked port and the edge configuration instead.

Reproduce this on a graded lab

Diagnose a seeded loop and a wrong root on real Cisco IOS in CML, then upload the config for a grade.

All spanning tree labs →

Practice on real Cisco IOS

Build it on real Cisco IOS and get instant pass/fail grading on your own config.