{"record":{"id":"75cebb214da5f170","repo":"astrid-runtime/astrid","slug":"gateway-has-no-live-capsule-provider-probe","errorCode":null,"errorMessage":"gateway has no live capsule provider probe","messagePattern":"gateway has no live capsule provider probe","errorType":"http","errorClass":"GatewayError::Internal","httpStatus":500,"severity":"critical","filePath":"crates/astrid-gateway/src/routes/models.rs","lineNumber":335,"sourceCode":"        if probe.is_subscribed(&key).await {\n            return Ok(());\n        }\n        if started.elapsed() >= timeout {\n            return Err(GatewayError::Internal(anyhow::anyhow!(\n                \"no loaded capsule handles the registry request for caller\"\n            )));\n        }\n        tokio::time::sleep(CAPSULE_PROBE_INTERVAL).await;\n    }\n}\n\nasync 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","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-gateway/src/routes/models.rs#L317-L353","documentation":"This GatewayError::Internal is thrown by `provider_source_ids` when `state.topic_probe` is `None`, meaning the gateway process never had (or no longer has) a live capsule provider probe wired into its state. Without the probe the gateway cannot discover which loaded capsule serves registry requests, so the models/registry routes cannot proceed. It indicates a gateway startup/wiring problem, not a client mistake.","triggerScenarios":"Any registry route that calls `registry_round_trip` -> `provider_source_ids` (GET /api/models, GET/PUT /api/models/active) while `GatewayState.topic_probe` is None — e.g. the probe handle was never installed at gateway construction or was replaced/removed after startup.","commonSituations":"Gateway started in a mode or test harness that does not attach a topic probe; a bootstrap change where probe initialization failed and the gateway kept running without it; partially initialized state after a failed event-bus connect.","solutions":["Restart the gateway with its normal bootstrap so `GatewayState.topic_probe` is populated before serving traffic.","Check gateway initialization/startup code for a path that constructs GatewayState without installing the topic probe; make probe installation mandatory and fail fast if absent.","Verify the kernel/capsule runtime the probe depends on is available and healthy; fix the underlying init failure rather than letting the gateway run probe-less.","If this appears only in tests, build the test GatewayState with a CapsuleTopicProbe instance (as the models.rs tests do)."],"exampleFix":"// before\nlet state = GatewayState { /* ... */ topic_probe: None };\n// after\nlet state = GatewayState { /* ... */ topic_probe: Some(Arc::new(CapsuleTopicProbe::new(event_bus))) };","handlingStrategy":"fallback","validationCode":"if gateway_state.topic_probe.is_none() {\n    return Err(anyhow!(\"gateway not initialized with a capsule provider probe; refusing registry request\"));\n}","typeGuard":"fn has_topic_probe(state: &GatewayState) -> bool {\n    state.topic_probe.is_some()\n}","tryCatchPattern":"match registry_round_trip(&state, /* ... */).await {\n    Err(e) if e.to_string().contains(\"no live capsule provider probe\") => {\n        // gateway misconfigured; fail fast / restart, do not retry the request\n        return StatusCode::SERVICE_UNAVAILABLE;\n    }\n    other => other?,\n}","preventionTips":["Make topic_probe a required constructor parameter of GatewayState so a probe-less state cannot be built","Fail fast at startup: health-check that topic_probe is Some before binding the listener","Add a readiness probe endpoint that reports probe presence so orchestrators keep a probe-less gateway out of rotation"],"tags":["rust","gateway","internal-error","initialization"],"backgroundTag":"missing-required-config","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}