{"record":{"id":"448f94fbb57a4619","repo":"zeroclaw-labs/zeroclaw","slug":"live-model-listing-is-not-supported-for-this-model","errorCode":null,"errorMessage":"live model listing is not supported for this model_provider","messagePattern":"live model listing is not supported for this model_provider","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"critical","filePath":"crates/zeroclaw-api/src/model_provider.rs","lineNumber":597,"sourceCode":"        model: &str,\n        temperature: Option<f64>,\n    ) -> anyhow::Result<String> {\n        self.chat_with_system(None, message, model, temperature)\n            .await\n    }\n\n    /// One-shot chat with optional system prompt. See `simple_chat` for\n    /// the `temperature` contract.\n    async fn chat_with_system(\n        &self,\n        system_prompt: Option<&str>,\n        message: &str,\n        model: &str,\n        temperature: Option<f64>,\n    ) -> anyhow::Result<String>;\n\n    async fn list_models(&self) -> anyhow::Result<Vec<String>> {\n        anyhow::bail!(\"live model listing is not supported for this model_provider\")\n    }\n\n    /// Fetch the list of available models with pricing data for this\n    /// model_provider. Default delegates to `list_models` and returns no\n    /// pricing. Concrete providers that receive pricing from their `/models`\n    /// endpoint override this to return enriched data.\n    async fn list_models_with_pricing(&self) -> anyhow::Result<Vec<ModelInfo>> {\n        Ok(self\n            .list_models()\n            .await?\n            .into_iter()\n            .map(|id| ModelInfo {\n                id,\n                pricing: None,\n                context_window: None,\n            })\n            .collect())\n    }","sourceCodeStart":579,"sourceCodeEnd":615,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-api/src/model_provider.rs#L579-L615","documentation":"tool_linker_http() is the HttpClient-granted linker variant, built lazily on the first plugin whose PluginInstanceScope grants HttpClient. Its first step builds the base linker (WASI plus tool bindings) with the same expect(\"tool linker\") used by the non-HTTP path. It fails for the same version/generation-skew reasons, but only HTTP-granted plugins trigger it — non-HTTP plugins keep working, which can mask the scope of the breakage.","triggerScenarios":"The first create_plugin() for a plugin with the HttpClient capability when wasmtime or the generated tool bindings are version-skewed; the OnceLock caches the panic-inducing initialization attempt context but the panic itself fires at first use.","commonSituations":"Mixed wasmtime versions after a partial dependency upgrade; a fork that regenerates bindings for the base world but not the HTTP world; CI passing non-HTTP plugin tests while HTTP plugins panic at runtime.","solutions":["Align wasmtime, wasmtime-wasi, and wasmtime-wasi-http on one version and rebuild.","Cover both linker paths with a startup smoke test that instantiates one HTTP-granted and one plain plugin.","Regenerate bindings from wit/v0 consistently for base and HTTP worlds.","If embedding, pre-create one HTTP plugin at startup so this surfaces as a boot failure with full context."],"exampleFix":"// before\nLINKER.get_or_init(|| {\n    let mut linker = base_linker().expect(\"tool linker\");\n    crate::component::add_wasi_http(&mut linker).expect(\"tool http linker\");\n    linker\n})\n\n// after — propagate instead of panicking\nstatic LINKER: OnceLock<anyhow::Result<Linker<PluginState>>> = OnceLock::new();\nLINKER.get_or_init(|| {\n    let mut linker = base_linker()?;\n    crate::component::add_wasi_http(&mut linker)\n        .map_err(|e| anyhow::anyhow!(\"wasi:http linker init failed: {e:#}\"))?;\n    Ok(linker)\n});","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Probe an HTTP-granted plugin at startup, not at first user request:\nlet probe = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    futures::executor::block_on(create_plugin(&http_plugin_path, &http_scope, limits))\n}));\nif probe.is_err() {\n    tracing::error!(\"HTTP plugin linker broken; disabling HttpClient plugins\");\n}","preventionTips":["Cover both linker paths (plain and HTTP) with smoke tests — non-HTTP plugins passing hides HTTP-path breakage","Upgrade wasmtime, wasmtime-wasi, and wasmtime-wasi-http as one unit","Pre-create warm plugins at startup so failures are boot-visible","Pin exact versions with `=x.y.z` if skew keeps reappearing"],"tags":["rust","wasmtime","wasi-http","plugins","version-mismatch","panic"],"backgroundTag":"wasmtime-linker-init-failed","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}