{"record":{"id":"99cf9c0fd27890b9","repo":"zeroclaw-labs/zeroclaw","slug":"memory-backend-does-not-support-agent-attribu","errorCode":null,"errorMessage":"memory backend '{}' does not support agent-attributed StoreOptions kind/pinned/tenant_id; use a backend that overrides store_with_options_and_agent","messagePattern":"memory backend '(.+?)' does not support agent-attributed StoreOptions kind/pinned/tenant_id; use a backend that overrides store_with_options_and_agent","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"critical","filePath":"crates/zeroclaw-api/src/memory_traits.rs","lineNumber":594,"sourceCode":"\n    /// Store a memory entry with full metadata and an explicit agent UUID.\n    ///\n    /// The compatibility default preserves agent attribution through the\n    /// established `store_with_agent` path for namespace and importance only.\n    /// Backends that persist the full `StoreOptions` surface override this\n    /// method so wrappers do not have to choose between attribution and typed\n    /// metadata.\n    async fn store_with_options_and_agent(\n        &self,\n        key: &str,\n        content: &str,\n        category: MemoryCategory,\n        session_id: Option<&str>,\n        options: StoreOptions,\n        agent_id: Option<&str>,\n    ) -> anyhow::Result<()> {\n        if options.requires_full_options_storage() {\n            anyhow::bail!(\n                \"memory backend '{}' does not support agent-attributed StoreOptions kind/pinned/tenant_id; use a backend that overrides store_with_options_and_agent\",\n                self.name()\n            );\n        }\n        self.store_with_agent(\n            key,\n            content,\n            category,\n            session_id,\n            options.namespace.as_deref(),\n            options.importance,\n            agent_id,\n        )\n        .await\n    }\n\n    /// Store a memory entry attributed to an explicit agent UUID.\n    /// Every backend must implement this explicitly so the agent_id","sourceCodeStart":576,"sourceCodeEnd":612,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-api/src/memory_traits.rs#L576-L612","documentation":"tool_linker() lazily builds, once per process via OnceLock, the wasmtime component Linker every tool plugin instantiates against: WASI Preview 2 imports plus the generated zeroclaw tool-world bindings (base_linker → ToolPlugin::add_to_linker). add_to_linker fails when import names collide or host signatures do not match what the engine expects — practically a version or generation mismatch between wasmtime, wasmtime-wasi, and the checked-in generated bindings. The expect fires on the first create_plugin() call and disables plugin tooling for the whole process.","triggerScenarios":"The first tool-plugin load after startup when wasmtime/wasmtime-wasi versions are skewed relative to the generated component bindings, or a fork defines overlapping imports on the same linker.","commonSituations":"Cargo updated wasmtime patch versions inconsistently; wasmtime-wasi or the bindings pinned to an older release; component bindings regenerated from a newer wit/v0 than the host crates support; local forks adding manual imports that clash with add_wasi.","solutions":["Pin wasmtime, wasmtime-wasi, and wasmtime-wasi-http to one identical version in Cargo.toml and run cargo update.","cargo clean and rebuild so generated bindings and engine versions agree.","Regenerate the component bindings from wit/v0 with the toolchain version the host crates expect.","If maintaining a fork, diff add_wasi/add_wasi_http usage against any manual linker definitions for duplicate imports.","If a stock checkout fails, report upstream with the exact wasmtime/wasi versions in Cargo.lock."],"exampleFix":"// before\nstatic LINKER: OnceLock<Linker<PluginState>> = OnceLock::new();\nLINKER.get_or_init(|| base_linker().expect(\"tool linker\"))\n\n// after — keep the Result so callers can degrade instead of panicking on first use\nstatic LINKER: OnceLock<anyhow::Result<Linker<PluginState>>> = OnceLock::new();\nLINKER.get_or_init(base_linker).as_ref()\n    .map_err(|e| anyhow::anyhow!(\"tool linker init failed: {e:#}\"))","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"// First plugin creation panics if the linker cannot build; contain it:\nlet probe = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    futures::executor::block_on(\n        zeroclaw_plugins::runtime::create_plugin(&wasm_path, &scope, limits),\n    )\n}));\nif probe.is_err() {\n    disable_plugins_and_log(); // degrade to native tools, keep the agent alive\n}","preventionTips":["Keep all wasmtime* crates on one locked version in Cargo.lock","Regenerate component bindings whenever wit/v0 changes","Add a startup smoke test that successfully creates one plugin","Make the plugin subsystem fail independently of the core runtime"],"tags":["rust","wasmtime","wasm","wasi","component-model","plugins","panic"],"backgroundTag":"wasmtime-linker-init-failed","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}