Repository navigation
[Duplicate of #5009] RoutingGrain dispatch budget saturated by head-of-line blocking on cache-destination legs across the portal fleet #5176
Description
What is failing
The mesh router (MeshWeaver.Hosting.Orleans.RoutingGrain) on the memex-cloud portal fleet repeatedly saturates its dispatch budget: all 64 route slots go in flight, and in nearly every sampled episode 62 of the 64 legs are queued behind a single destination (stream destinations queued 1, deepest per-destination queue 62). That is head-of-line blocking on one destination, not load — one destination's leg holds the queue while ~62 other dispatches wait behind it.
Probable cause
Moderately confident: the blocked destinations in every readable sample are cache/<id> addresses (cache invalidation/fan-out subscribers). A single slow or wedged cache subscriber leg holds its destination queue, and since routing slots are held from dispatch until the leg terminates — including the unbounded wait for a ThreadPool thread — a slow cache leg (or thread-pool starvation triggered by it) pins the router. The episode stamps matter: samples show fresh episode ids roughly every 2–10 minutes with episode number #1, i.e. episodes drain and immediately recur rather than one permanently leaked slot (a leaked slot would show the same activation+episode with no higher episode ever following). So the router is repeatedly degraded, not permanently wedged — pointing at a recurring slow cache leg rather than the shutdown-cancellation slot leak fixed on 2026-08-12. Lower confidence on why the cache leg is slow (subscriber I/O vs ThreadPool starvation); the evidence does not distinguish those.
Impact
88 critical bursts over ~9.5 hours (2026-09-21 12:32–22:10 UTC) across all 8 portal pods. Each episode means the pod's routing capacity is fully consumed and non-cache destinations' dispatches queue behind the blocked leg — portal message delivery (including non-cache traffic) is intermittently delayed fleet-wide for the whole period. No evidence of data loss or permanent wedge; episodes clear.
Where to look
MeshWeaver.Hosting.Orleans.RoutingGrain— the per-destination leg queue and the slot-release path on leg termination; log site[ROUTE].- The cache destination subscriber (
cache/*stream, e.g.cache/FtxSQnNgjkmJzr-09vwCJQ,cache/adQjx8eg8UyB5mWb_cRd5Q— both recur across pods) — what its legs wait on. - Prior art: Routing back-pressure alerts now name what they actually saw (slot-leak fix and alert semantics) and ActionBlockWedgePrevention.
Note: this is one of ~20 sibling back-pressure incidents opened on 2026-09-19..21 (e.g. Admin/_LogIncident/0fc7665eaf6aae43, Admin/_LogIncident/155d7ffcac9123d3) — likely the same underlying episode; consolidating them under this ticket is reasonable.
Evidence
| Fingerprint | 96c85f04cadba7f7 |
| Category | MeshWeaver.Hosting.Orleans.RoutingGrain |
| Severity | Critical |
| Namespace | memex-cloud |
| Pods | memex-portal-deployment-77494bdbcc-7ndrn, memex-portal-deployment-7fc5f4874b-tl6zn, memex-portal-deployment-7fc5f4874b-9zwrg, memex-portal-deployment-77494bdbcc-bphfb, memex-portal-deployment-8d98c8fc6-w6clj, memex-portal-deployment-8d98c8fc6-f674p, memex-portal-deployment-7b4776b9f-mqfr6, memex-portal-deployment-7b4776b9f-8khld |
| Occurrences | 88 |
| First seen | 2026-09-21 12:32:25Z |
| Last seen | 2026-09-21 22:10:25Z |
| Routing | not determined — no configured route matches the category MeshWeaver.Hosting.Orleans.RoutingGrain. This repository is the configured fallback, not a finding about who owns the fault; the category names the LOGGER, which may not be the subject. |
Recent log lines
2026-09-21 20:57:24Z memex-portal-deployment-8d98c8fc6-f674p fail: MeshWeaver.Hosting.Orleans.RoutingGrain[0]
2026-09-21 20:59:24Z memex-portal-deployment-8d98c8fc6-f674p crit: MeshWeaver.Hosting.Orleans.RoutingGrain[0]
[ROUTE] Routing back-pressure [cde6effa#1 started 2026-09-21T20:59:24.2992913Z]: 64 route dispatches in flight (reporting threshold 64); stream destinations queued 3, deepest per-destination queue 26, routing pool subscribing 1. Latest dispatch target cache/adQjx8eg8UyB5mWb_cRd5Q — the address that happened to cross the threshold, NOT a diagnosis. A slot is held from dispatch until the leg terminates, INCLUDING the unbounded wait for a ThreadPool thread before the leg's own timeouts start, so a CPU-starved silo raises this with nothing stuck. A deepest queue of 1 or more means legs are blocked behind a leg (head-of-line on one destination); 0 means nothing is waiting on anything, so read it as load. 🚨 Deepest is sampled AT THE CROSSING, so like the in-flight count it is partly an artefact of the threshold: with N destinations sharing the backlog it is ~InFlight/N whatever is wrong. READ THE EPISODE STAMP, not the depth: a later line with a HIGHER episode on this activation means this episode drained; a line with a DIFFERENT activation id means the grain was recycled; and if neither a clear nor a higher episode ever follows, the in-flight count never fell below half the threshold — which means a leg never terminated and its slot leaked, not that the silo was busy.
2026-09-21 21:07:24Z memex-portal-deployment-7b4776b9f-mqfr6 crit: MeshWeaver.Hosting.Orleans.RoutingGrain[0]
[ROUTE] Routing back-pressure [cc8c953f#1 started 2026-09-21T21:07:24.3065069Z]: 64 route dispatches in flight (reporting threshold 64); stream destinations queued 1, deepest per-destination queue 62, routing pool subscribing 0. Latest dispatch target cache/rsFtZ2Qxwkmoo8tSu3Yzww — the address that happened to cross the threshold, NOT a diagnosis. A slot is held from dispatch until the leg terminates, INCLUDING the unbounded wait for a ThreadPool thread before the leg's own timeouts start, so a CPU-starved silo raises this with nothing stuck. A deepest queue of 1 or more means legs are blocked behind a leg (head-of-line on one destination); 0 means nothing is waiting on anything, so read it as load. 🚨 Deepest is sampled AT THE CROSSING, so like the in-flight count it is partly an artefact of the threshold: with N destinations sharing the backlog it is ~InFlight/N whatever is wrong. READ THE EPISODE STAMP, not the depth: a later line with a HIGHER episode on this activation means this episode drained; a line with a DIFFERENT activation id means the grain was recycled; and if neither a clear nor a higher episode ever follows, the in-flight count never fell below half the threshold — which means a leg never terminated and its slot leaked, not that the silo was busy.
2026-09-21 21:09:25Z memex-portal-deployment-77494bdbcc-7ndrn crit: MeshWeaver.Hosting.Orleans.RoutingGrain[0]
[ROUTE] Routing back-pressure [67cc298f#1 started 2026-09-21T21:09:25.1695035Z]: 64 route dispatches in flight (reporting threshold 64); stream destinations queued 1, deepest per-destination queue 62, routing pool subscribing 0. Latest dispatch target cache/mr9jbhbuyEGL3xTrvoGS9g — the address that happened to cross the threshold, NOT a diagnosis. A slot is held from dispatch until the leg terminates, INCLUDING the unbounded wait for a ThreadPool thread before the leg's own timeouts start, so a CPU-starved silo raises this with nothing stuck. A deepest queue of 1 or more means legs are blocked behind a leg (head-of-line on one destination); 0 means nothing is waiting on anything, so read it as load. 🚨 Deepest is sampled AT THE CROSSING, so like the in-flight count it is partly an artefact of the threshold: with N destinations sharing the backlog it is ~InFlight/N whatever is wrong. READ THE EPISODE STAMP, not the depth: a later line with a HIGHER episode on this activation means this episode drained; a line with a DIFFERENT activation id means the grain was recycled; and if neither a clear nor a higher episode ever follows, the in-flight count never fell below half the threshold — which means a leg never terminated and its slot leaked, not that the silo was busy.
2026-09-21 21:14:24Z memex-portal-deployment-8d98c8fc6-f674p crit: MeshWeaver.Hosting.Orleans.RoutingGrain[0]
[ROUTE] Routing back-pressure [e02bc619#1 started 2026-09-21T21:14:24.3475160Z]: 64 route dispatches in flight (reporting threshold 64); stream destinations queued 3, deepest per-destination queue 26, routing pool subscribing 0. Latest dispatch target cache/FtxSQnNgjkmJzr-09vwCJQ — the address that happened to cross the threshold, NOT a diagnosis. A slot is held from dispatch until the leg terminates, INCLUDING the unbounded wait for a ThreadPool thread before the leg's own timeouts start, so a CPU-starved silo raises this with nothing stuck. A deepest queue of 1 or more means legs are blocked behind a leg (head-of-line on one destination); 0 means nothing is waiting on anything, so read it as load. 🚨 Deepest is sampled AT THE CROSSING, so like the in-flight count it is partly an artefact of the threshold: with N destinations sharing the backlog it is ~InFlight/N whatever is wrong. READ THE EPISODE STAMP, not the depth: a later line with a HIGHER episode on this activation means this episode drained; a line with a DIFFERENT activation id means the grain was recycled; and if neither a clear nor a higher episode ever follows, the in-flight count never fell below half the threshold — which means a leg never terminated and its slot leaked, not that the silo was busy.
2026-09-21 21:47:24Z memex-portal-deployment-7b4776b9f-8khld crit: MeshWeaver.Hosting.Orleans.RoutingGrain[0]
[ROUTE] Routing back-pressure [707c966f#1 started 2026-09-21T21:47:24.3005854Z]: 64 route dispatches in flight (reporting threshold 64); stream destinations queued 1, deepest per-destination queue 62, routing pool subscribing 1. Latest dispatch target cache/FtxSQnNgjkmJzr-09vwCJQ — the address that happened to cross the threshold, NOT a diagnosis. A slot is held from dispatch until the leg terminates, INCLUDING the unbounded wait for a ThreadPool thread before the leg's own timeouts start, so a CPU-starved silo raises this with nothing stuck. A deepest queue of 1 or more means legs are blocked behind a leg (head-of-line on one destination); 0 means nothing is waiting on anything, so read it as load. 🚨 Deepest is sampled AT THE CROSSING, so like the in-flight count it is partly an artefact of the threshold: with N destinations sharing the backlog it is ~InFlight/N whatever is wrong. READ THE EPISODE STAMP, not the depth: a later line with a HIGHER episode on this activation means this episode drained; a line with a DIFFERENT activation id means the grain was recycled; and if neither a clear nor a higher episode ever follows, the in-flight count never fell below half the threshold — which means a leg never terminated and its slot leaked, not that the silo was busy.
2026-09-21 21:59:24Z memex-portal-deployment-7b4776b9f-mqfr6 crit: MeshWeaver.Hosting.Orleans.RoutingGrain[0]
[ROUTE] Routing back-pressure [000c904f#1 started 2026-09-21T21:59:24.2321318Z]: 64 route dispatches in flight (reporting threshold 64); stream destinations queued 1, deepest per-destination queue 62, routing pool subscribing 0. Latest dispatch target cache/adQjx8eg8UyB5mWb_cRd5Q — the address that happened to cross the threshold, NOT a diagnosis. A slot is held from dispatch until the leg terminates, INCLUDING the unbounded wait for a ThreadPool thread before the leg's own timeouts start, so a CPU-starved silo raises this with nothing stuck. A deepest queue of 1 or more means legs are blocked behind a leg (head-of-line on one destination); 0 means nothing is waiting on anything, so read it as load. 🚨 Deepest is sampled AT THE CROSSING, so like the in-flight count it is partly an artefact of the threshold: with N destinations sharing the backlog it is ~InFlight/N whatever is wrong. READ THE EPISODE STAMP, not the depth: a later line with a HIGHER episode on this activation means this episode drained; a line with a DIFFERENT activation id means the grain was recycled; and if neither a clear nor a higher episode ever follows, the in-flight count never fell below half the threshold — which means a leg never terminated and its slot leaked, not that the silo was busy.
2026-09-21 21:59:24Z memex-portal-deployment-7b4776b9f-mqfr6 crit: MeshWeaver.Hosting.Orleans.RoutingGrain[0]
[ROUTE] Routing back-pressure [000c904f#1 started 2026-09-21T21:59:24.2321318Z]: 64 route dispatches in flight (reporting threshold 64); stream destinations queued 1, deepest per-destination queue 62, routing pool subscribing 0. Latest dispatch target cache/adQjx8eg8UyB5mWb_cRd5Q — the address that happened to cross the threshold, NOT a diagnosis. A slot is held from dispatch until the leg terminates, INCLUDING the unbounded wait for a ThreadPool thread before the leg's own timeouts start, so a CPU-starved silo raises this with nothing stuck. A deepest queue of 1 or more means legs are blocked behind a leg (head-of-line on one destination); 0 means nothing is waiting on anything, so read it as load. 🚨 Deepest is sampled AT THE CROSSING, so like the in-flight count it is partly an artefact of the threshold: with N destinations sharing the backlog it is ~InFlight/N whatever is wrong. READ THE EPISODE STAMP, not the depth: a later line with a HIGHER episode on this activation means this episode drained; a line with a DIFFERENT activation id means the grain was recycled; and if neither a clear nor a higher episode ever follows, the in-flight count never fell below half the threshold — which means a leg never terminated and its slot leaked, not that the silo was busy.
2026-09-21 22:10:24Z memex-portal-deployment-7b4776b9f-mqfr6 crit: MeshWeaver.Hosting.Orleans.RoutingGrain[0]
[ROUTE] Routing back-pressure [aa98ed14#1 started 2026-09-21T22:10:24.2838546Z]: 64 route dispatches in flight (reporting threshold 64); stream destinations queued 1, deepest per-destination queue 62, routing pool subscribing 0. Latest dispatch target cache/adQjx8eg8UyB5mWb_cRd5Q — the address that happened to cross the threshold, NOT a diagnosis. A slot is held from dispatch until the leg terminates, INCLUDING the unbounded wait for a ThreadPool thread before the leg's own timeouts start, so a CPU-starved silo raises this with nothing stuck. A deepest queue of 1 or more means legs are blocked behind a leg (head-of-line on one destination); 0 means nothing is waiting on anything, so read it as load. 🚨 Deepest is sampled AT THE CROSSING, so like the in-flight count it is partly an artefact of the threshold: with N destinations sharing the backlog it is ~InFlight/N whatever is wrong. READ THE EPISODE STAMP, not the depth: a later line with a HIGHER episode on this activation means this episode drained; a line with a DIFFERENT activation id means the grain was recycled; and if neither a clear nor a higher episode ever follows, the in-flight count never fell below half the threshold — which means a leg never terminated and its slot leaked, not that the silo was busy.
2026-09-21 22:10:25Z memex-portal-deployment-77494bdbcc-7ndrn crit: MeshWeaver.Hosting.Orleans.RoutingGrain[0]
[ROUTE] Routing back-pressure [485b1c95#1 started 2026-09-21T22:10:25.2081129Z]: 64 route dispatches in flight (reporting threshold 64); stream destinations queued 1, deepest per-destination queue 62, routing pool subscribing 0. Latest dispatch target cache/xFMO23Y5r0uAuw3jmEtZpQ — the address that happened to cross the threshold, NOT a diagnosis. A slot is held from dispatch until the leg terminates, INCLUDING the unbounded wait for a ThreadPool thread before the leg's own timeouts start, so a CPU-starved silo raises this with nothing stuck. A deepest queue of 1 or more means legs are blocked behind a leg (head-of-line on one destination); 0 means nothing is waiting on anything, so read it as load. 🚨 Deepest is sampled AT THE CROSSING, so like the in-flight count it is partly an artefact of the threshold: with N destinations sharing the backlog it is ~InFlight/N whatever is wrong. READ THE EPISODE STAMP, not the depth: a later line with a HIGHER episode on this activation means this episode drained; a line with a DIFFERENT activation id means the grain was recycled; and if neither a clear nor a higher episode ever follows, the in-flight count never fell below half the threshold — which means a leg never terminated and its slot leaked, not that the silo was busy.
Re-addressed by the current identity function: this incident inherited e4a97855ab595beb (Systemorph/MeshWeaver.Plugins#1796). Those nodes are superseded and will not fold, file or comment again.
Opened automatically from Admin/_LogIncident/96c85f04cadba7f7. Recurrences are folded into this issue rather than opening new ones.
Activity
systemorph-com commentedon Sep 22, 2026
Still occurring: 1 more since the last update (89 total).
memex-portal-deployment-77494bdbcc-7ndrn,memex-portal-deployment-7fc5f4874b-tl6zn,memex-portal-deployment-7fc5f4874b-9zwrg,memex-portal-deployment-77494bdbcc-bphfb,memex-portal-deployment-8d98c8fc6-w6clj,memex-portal-deployment-8d98c8fc6-f674p,memex-portal-deployment-7b4776b9f-mqfr6,memex-portal-deployment-7b4776b9f-8khldRecent log lines
Re-addressed by the current identity function: this incident inherited
e4a97855ab595beb(Systemorph/MeshWeaver.Plugins#1796). Those nodes are superseded and will not fold, file or comment again.systemorph-com commentedon Sep 22, 2026
Still occurring: 1 more since the last update (90 total).
memex-portal-deployment-77494bdbcc-7ndrn,memex-portal-deployment-7fc5f4874b-tl6zn,memex-portal-deployment-7fc5f4874b-9zwrg,memex-portal-deployment-77494bdbcc-bphfb,memex-portal-deployment-8d98c8fc6-w6clj,memex-portal-deployment-8d98c8fc6-f674p,memex-portal-deployment-7b4776b9f-mqfr6,memex-portal-deployment-7b4776b9f-8khldRecent log lines
Re-addressed by the current identity function: this incident inherited
e4a97855ab595beb(Systemorph/MeshWeaver.Plugins#1796). Those nodes are superseded and will not fold, file or comment again.systemorph-com commentedon Sep 22, 2026
Still occurring: 1 more since the last update (91 total).
memex-portal-deployment-77494bdbcc-7ndrn,memex-portal-deployment-7fc5f4874b-tl6zn,memex-portal-deployment-7fc5f4874b-9zwrg,memex-portal-deployment-77494bdbcc-bphfb,memex-portal-deployment-8d98c8fc6-w6clj,memex-portal-deployment-8d98c8fc6-f674p,memex-portal-deployment-7b4776b9f-mqfr6,memex-portal-deployment-7b4776b9f-8khldRecent log lines
Re-addressed by the current identity function: this incident inherited
e4a97855ab595beb(Systemorph/MeshWeaver.Plugins#1796). Those nodes are superseded and will not fold, file or comment again.systemorph-com commentedon Sep 22, 2026
Still occurring: 2 more since the last update (93 total).
memex-portal-deployment-77494bdbcc-7ndrn,memex-portal-deployment-7fc5f4874b-tl6zn,memex-portal-deployment-7fc5f4874b-9zwrg,memex-portal-deployment-77494bdbcc-bphfb,memex-portal-deployment-8d98c8fc6-w6clj,memex-portal-deployment-8d98c8fc6-f674p,memex-portal-deployment-7b4776b9f-mqfr6,memex-portal-deployment-7b4776b9f-8khldRecent log lines
Re-addressed by the current identity function: this incident inherited
e4a97855ab595beb(Systemorph/MeshWeaver.Plugins#1796). Those nodes are superseded and will not fold, file or comment again.systemorph-com commentedon Sep 22, 2026
Still occurring: 3 more since the last update (96 total).
memex-portal-deployment-77494bdbcc-7ndrn,memex-portal-deployment-7fc5f4874b-tl6zn,memex-portal-deployment-7fc5f4874b-9zwrg,memex-portal-deployment-77494bdbcc-bphfb,memex-portal-deployment-8d98c8fc6-w6clj,memex-portal-deployment-8d98c8fc6-f674p,memex-portal-deployment-7b4776b9f-mqfr6,memex-portal-deployment-7b4776b9f-8khldRecent log lines
Re-addressed by the current identity function: this incident inherited
e4a97855ab595beb(Systemorph/MeshWeaver.Plugins#1796). Those nodes are superseded and will not fold, file or comment again.[-]RoutingGrain dispatch budget saturated by head-of-line blocking on cache-destination legs across the portal fleet[/-][+][Duplicate of #5009] RoutingGrain dispatch budget saturated by head-of-line blocking on cache-destination legs across the portal fleet[/+]rbuergi commentedon Sep 22, 2026
Closing as a duplicate of #5009 — the same condition, re-reported from a pre-fix image. A duplicate disposition asserts nothing about the fix; #5009 stays open and closes only on production verification.
Same condition. Every retained sample here is #5009's head-of-line shape exactly: 64 in flight,
stream destinations queued 1, deepest per-destination queue 62, targetcache/<meshId>, episode stamps at#1that drain and recur (the two deepest-26-over-3 lines are the same backlog split three ways — ~InFlight/N, as the line itself says). The addresses recur across pods (cache/FtxSQnNgjkmJzr-09vwCJQ,cache/adQjx8eg8UyB5mWb_cRd5Q), which is #5151's diagnosed mechanism:cache/{meshId}is per PROCESS, so the queue that stacks is each pod's channel to a PEER pod's cache hub, one network round trip per frame, and this fleet has 8 pods where #5009 had 2 — more cross-silo channels, more of exactly this. Both incidents were re-addressed out of the same old category-wide fingerprinte4a97855ab595beb(=SHA256("MeshWeaver.Hosting.Orleans.RoutingGrain\n0\n")[..8], perDoc/Architecture/LogWatchTriage), which is why one condition holds two tickets.The fix is merged and not live. PR #5151 (merged
78bbf49e03, 2026-09-21T22:43Z) re-keysOrderedRouteDispatcher's FIFO from the destination address to the(destination, stream)pair, so independent streams stop waiting on each other. Three independent readings say no sample here came from an image carrying it:93total) — the last 20 minutes are after the merge, none are after a roll.ordered channels queued N over M stream destination(s), deepest per-channel queue D. All 93 folded occurrences print the pre-fixstream destinations queued …, deepest per-destination queue …. A post-fix(routing): the ordering FIFO's channel is (destination, stream), not the destination #5151 image cannot emit that sentence.Ops/Status/*on the control instance, sampled 2026-09-22T06:13Z,converged: true): memex-cloud 6/6 on3.0.0-ci.9076= commit026442fff0(fix(#4716): a submission inbox on a public partition — the grant shape both permission folds agree on, and a boot heal that stopped deleting it #5043); memex 2/2 on3.0.0-ci.9106=8a52945608(feat(comms): the Communication Hub — open vocabularies, durable dispatch chain, and the first enum conversion #5044).git merge-base --is-ancestor 78bbf49e03 <running>→ NO for both; control: the memex commit IS an ancestor of the fix(routing): the ordering FIFO's channel is (destination, stream), not the destination #5151 merge, i.e. older.The
podslist here spans BOTH portals' current generations (77494bdbccis memex-cloud's,7b4776b9fis memex's) plus two retired ones — thenamespace: memex-cloudfield is the first-seen namespace, not the population.Not folded, deliberately: nothing here carries #5018's
deepest 0load shape; that ticket is untouched by this and by #5151.What closes #5009 (and would re-open this question): after a roll carrying
78bbf49e03, a crossing that printsdeepest per-channel queue≥ 1 is frames of ONE stream stacking — a genuinely stuck leg, a different defect. A crossing printing many channels over few destinations with deepest 0 is load. A line still printingper-destinationon a post-roll pod is the roll not having reached that pod.