"Does Junos apply next-hop self automatically?" — that r/Juniper question captures the whole topic. Coming from Cisco IOS, engineers expect next-hop-self to be a knob they must set on iBGP; Junos behaves differently by default, and the resulting confusion produces the weekly "routes not advertised" thread. Here is how it really works, and how to verify every link in the advertisement chain.

The Default Junos Behavior for Next Hop

Junos rewrites the BGP next hop automatically when a route is advertised to an eBGP peer (the advertising router becomes the next hop). Between iBGP peers, the next hop is preserved by default — so if your internal peers have no route to the original next hop, the route arrives hidden: present in the BGP table, ineligible for use and (critically) not re-advertised onward. Juniper's KB on BGP NEXT_HOP self configuration walks precisely this failure.

On iBGP peers that exchange routes learned from eBGP, the standard fix is an export policy that rewrites the next hop:

policy-statement NH-SELF {
    term 1 {
        then next-hop self;
    }
}
protocols bgp group IBGP export NH-SELF;

On route reflectors, next-hop self is not applied automatically to reflected routes either — the route-reflector next hop discussion on the Juniper community covers when to add it. The r/Juniper thread about automatic next-hop-self confirms the eBGP-only default that surprises Cisco engineers.

Step 1: Verify What You Advertise — from the Right Vantage Point

show route advertising-neighbor 203.0.113.2
show route receive-neighbor 203.0.113.2

The first command shows exactly what your router sends to that neighbor; the second shows what you receive. If a route is missing from advertising-neighbor, the problem is local policy or eligibility — never the neighbor.

Step 2: Find Hidden Routes and Ask Why

show route 10.20.0.0/16 hidden detail
show route 10.20.0.0/16 detail

Hidden reasons are spelled out: Unusable next hop, Rejected by import policy, or Martian. An unusable next hop on iBGP-learned routes is the next-hop-self case above. Fix the next hop (or the IGP reachability to it — our OSPF on MX working example builds the usual carrier network that carries it) and the route becomes eligible and starts propagating.

Step 3: Export Policy — the Defaults Nobody Reads

Junos's default BGP export behavior: re-advertise all eligible BGP routes to peers, respecting iBGP split horizon. The moment you configure any export policy on the group or neighbor, the default is gone — your policy becomes the only gatekeeper, and a policy without a final accepting term rejects everything else:

policy-statement ADV {
    term direct {
        from protocol direct;
        then accept;
    }
    term static {
        from protocol static;
        then accept;
    }
    term bgp {
        from protocol bgp;
        then accept;
    }
}

Also remember: only routes in inet.0 that are active (best path) are advertised. A route shadowed by a better path — a more specific static, a leaked VRF route, or an aggregate — will simply not export. Check with show route 10.20.0.0/16 detail and look at which protocol won.

Step 4: Aggregates and Missing Contributors

If you advertise aggregates, the aggregate route only exists while at least one contributing route is active. Losing the contributor silently withdraws the aggregate:

show route aggregate
show route 10.20.0.0/16 detail | match contribute

The 60-Second Verification Matrix

SymptomCheckTypical fix
Route missing from advertising-neighborexport policy + active routeAdd accepting term / resolve shadowing route
Route received but hiddenshow route ... hidden detailnext-hop self on iBGP / fix IGP reachability
iBGP route not re-advertised to another iBGP peersplit horizon by designFull mesh or route reflection
Aggregate withdrawn intermittentlyshow route aggregateStabilize contributing routes

For sessions that never form at all, our BGP stuck in Active/Connect guide is the entry point; for sessions that form and then flap, use the BGP flap field method; and if churn is loading the box while you debug, check the routing engine CPU guide — rpd load from policy evaluation is common when every peer receives a big export policy.