{"record":{"id":"ba479cddf1f3c3a1","repo":"astrid-runtime/astrid","slug":"no-unique-compatible-loaded-capsule-handles-the-re","errorCode":null,"errorMessage":"no unique compatible loaded capsule handles the registry request for caller","messagePattern":"no unique compatible loaded capsule handles the registry request for caller","errorType":"http","errorClass":"GatewayError::Internal","httpStatus":500,"severity":"error","filePath":"crates/astrid-gateway/src/routes/models.rs","lineNumber":347,"sourceCode":"async fn provider_source_ids(\n    state: &GatewayState,\n    principal: &PrincipalId,\n    request_topic: &str,\n) -> GatewayResult<Vec<Uuid>> {\n    let probe = state.topic_probe.as_ref().ok_or_else(|| {\n        GatewayError::Internal(anyhow::anyhow!(\n            \"gateway has no live capsule provider probe\"\n        ))\n    })?;\n    let key = scoped_topic_probe_key(principal, request_topic);\n    if !probe.is_subscribed(&key).await && !probe.ensure_subscribed(&key).await {\n        return Err(GatewayError::Internal(anyhow::anyhow!(\n            \"no loaded capsule handles the registry request for caller\"\n        )));\n    }\n    let source_ids = probe.subscriber_source_ids(&key).await;\n    if source_ids.is_empty() {\n        return Err(GatewayError::Internal(anyhow::anyhow!(\n            \"no unique compatible loaded capsule handles the registry request for caller\"\n        )));\n    }\n    Ok(source_ids)\n}\n\nfn scoped_topic_probe_key(principal: &PrincipalId, topic: &str) -> String {\n    format!(\n        \"{SCOPED_SERVICE_PROBE_SENTINEL}{principal}\\0astrid\\0registry\\0{REGISTRY_INTERFACE_REQUIREMENT}\\0{topic}\"\n    )\n}\n\n/// `GET /api/models` — list the caller's available provider-entries.\n#[utoipa::path(\n    get,\n    path = \"/api/models\",\n    tag = \"models\",\n    responses(","sourceCodeStart":329,"sourceCodeEnd":365,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-gateway/src/routes/models.rs#L329-L365","documentation":"`provider_source_ids` throws this GatewayError::Internal when the topic probe IS subscribed for the scoped key, but `subscriber_source_ids` returns an empty list. The subscription exists yet no unique compatible loaded capsule is registered as a source for it — the gateway found the topic but no provider instance that can answer with a usable source id.","triggerScenarios":"Calling `registry_round_trip` where the probe is subscribed to `scoped_topic_probe_key(principal, request_topic)` but `probe.subscriber_source_ids(&key).await` yields an empty Vec.","commonSituations":"A capsule subscribed to the probe topic but never registered its provider source id; a stale subscription left after the capsule was unloaded or crashed; a race where the probe saw the subscription before the capsule completed registration; an inconsistent registry state with zero registered provider instances.","solutions":["Inspect which capsules are loaded and confirm the registry provider capsule registered its source id after subscribing; restart/reload the capsule so registration completes.","Check for a stale probe subscription from an unloaded capsule; clear/reset the probe subscription state and retry.","Look for races between subscription and source registration in the capsule load path and make registration atomic with subscription.","Check kernel/capsule logs for errors during provider registration that left the subscription present but the source list empty."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"let ids = probe.subscriber_source_ids(&key).await;\nif ids.is_empty() {\n    return Err(anyhow!(\"no capsule source registered for {key}; aborting registry request\"));\n}","typeGuard":"fn has_provider_source(ids: &[Uuid]) -> bool {\n    !ids.is_empty()\n}","tryCatchPattern":"match registry_round_trip(&state, /* ... */).await {\n    Err(e) if e.to_string().contains(\"no unique compatible loaded capsule\") => {\n        // transient: subscription present but source registration lagging — retry once, then 503\n        Err(StatusCode::SERVICE_UNAVAILABLE)\n    }\n    other => other?,\n}","preventionTips":["Make capsules register their source id atomically with topic subscription","Treat subscriptions with zero registered sources as unhealthy and re-register them","Log and alert on the subscription-vs-registration race so stale probe keys get cleaned up"],"tags":["rust","gateway","capsule","routing"],"backgroundTag":"empty-result-set","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}