What it is
A virtual network peering whose peeringState is anything other than Connected. The peering resource exists, it shows up in the portal, and it looks configured, but no traffic crosses it. Typically it was created on one VNet and never completed on the other, or the remote side was deleted and the local half was left behind.
Why it happens
Azure models a peering as two separate resources: one on each virtual network, each pointing at the other. Traffic flows only when both exist and both report Connected. Create just one half and it sits in Initiated, waiting for a counterpart that may never come. Delete either half later, say during a resource-group cleanup or a subscription migration, and the surviving half flips to Disconnected.
Nothing alerts on either transition. The half-peering is not an error to Azure; it's a valid resource in a valid state. The two halves also often live in different subscriptions owned by different teams, so the side that broke the link isn't the side that notices. It surfaces later as a confusing connectivity failure: DNS resolves, NSGs allow the traffic, and packets still go nowhere because there is no route across the dead peering.
What it costs / blast radius
Peering itself has no idle charge; you pay per GB transferred, and a dead peering transfers nothing. The damage is operational. In a hub-and-spoke topology, a spoke with a broken hub peering loses shared services in one step: private DNS, domain controllers, the firewall it routes through, on-prem connectivity via the hub's gateway. Because everything else looks healthy, these failures burn hours of troubleshooting at exactly the wrong moment, sometimes during the DR failover or migration that disturbed the peering in the first place. (Authored assessment of Azure behavior.)
See it
Resources
| where type =~ 'microsoft.network/virtualnetworks'
| mv-expand peering = properties.virtualNetworkPeerings
| extend state = tostring(peering.properties.peeringState)
| where isnotempty(state) and state != 'Connected'
| project vnet = name, resourceGroup, subscriptionId,
peering = tostring(peering.name), state,
remoteVnet = tostring(peering.properties.remoteVirtualNetwork.id)# Re-create the missing half on the remote VNet; both sides then
# converge to Connected.
az network vnet peering create --name spoke-to-hub \
--resource-group rg-spoke --vnet-name spoke-vnet \
--remote-vnet /subscriptions/<sub-id>/resourceGroups/rg-hub/providers/Microsoft.Network/virtualNetworks/hub-vnet \
--allow-vnet-access
# If both halves exist but drifted (e.g. after an address-space change):
az network vnet peering sync --name hub-to-spoke \
--resource-group rg-hub --vnet-name hub-vnet
# If the link is genuinely retired, delete the leftover half instead:
az network vnet peering delete --name spoke-to-hub \
--resource-group rg-spoke --vnet-name spoke-vnetHow StratoLens helps
StratoLens inspects every peering on every VNet across all your subscriptions and flags any that aren't Connected, with the state and the remote network it was supposed to reach. Because it sees both subscriptions in one view, the half-created peering gets caught when it's a five-minute fix, not during the outage postmortem.