zeroclaw-labs/zeroclaw · error · anyhow::Error
memory backend '{}' does not support StoreOptions kind/pinne
Error message
memory backend '{}' does not support StoreOptions kind/pinned/tenant_id; use a backend that overrides store_with_options What it means
install_global_subscriber is the single logging entry point for daemon binaries: it stacks LogCaptureLayer under an alias-prefixed stderr formatter and calls tracing::subscriber::set_global_default. tracing allows exactly one global default per process; set_global_default returns Err when one is already installed, and this expect converts that into a panic. The crate already ships non-panicking siblings — try_install_capture_subscriber and try_install_line_sink_for_tests — which ignore the same error.
Source
Thrown at crates/zeroclaw-api/src/memory_traits.rs:561
self.store(key, content, category, session_id).await
}
/// Store a memory entry with the full additive metadata surface.
///
/// Default delegates through the existing metadata method for namespace and
/// importance only. Backends that do not override this must fail explicitly
/// when callers pass typed/full metadata, rather than silently discarding
/// data needed by later typed-memory readers.
async fn store_with_options(
&self,
key: &str,
content: &str,
category: MemoryCategory,
session_id: Option<&str>,
options: StoreOptions,
) -> anyhow::Result<()> {
if options.requires_full_options_storage() {
anyhow::bail!(
"memory backend '{}' does not support StoreOptions kind/pinned/tenant_id; use a backend that overrides store_with_options",
self.name()
);
}
self.store_with_metadata(
key,
content,
category,
session_id,
options.namespace.as_deref(),
options.importance,
)
.await
}
/// Store a memory entry with full metadata and an explicit agent UUID.
///
/// The compatibility default preserves agent attribution through theView on GitHub (pinned to 88bb9c8533)
Solutions
- Install exactly once at process start; guard the call with std::sync::Once or check tracing::dispatcher::has_been_set() first.
- For secondary or embedded contexts use zeroclaw_log::try_install_capture_subscriber(), which ignores an already-set default.
- In tests, prefer per-test scoped subscribers (tracing::subscriber::with_default) or the crate's try_install_line_sink_for_tests().
- Grep the dependency graph for set_global_default, fmt::init, or env_logger init to find the competing installer.
Example fix
// before zeroclaw_log::install_global_subscriber(None, "info", false); zeroclaw_log::install_global_subscriber(None, "info", true); // second call panics // after static LOG_INIT: std::sync::Once = std::sync::Once::new(); LOG_INIT.call_once(|| zeroclaw_log::install_global_subscriber(None, "info", false));
Defensive patterns
Strategy: validation
Validate before calling
// Before installing:
if !tracing::dispatcher::has_been_set() {
zeroclaw_log::install_global_subscriber(None, "info", false);
} else {
zeroclaw_log::try_install_capture_subscriber(); // non-panicking fallback
} Try / catch
// If third-party code may race you to the global default:
let r = std::panic::catch_unwind(|| {
zeroclaw_log::install_global_subscriber(None, "info", false);
});
if r.is_err() {
// another subscriber won the race; keep it and continue with its output
} Prevention
- Initialize logging in main() before spawning tasks, exactly once
- Never call subscriber installation from library code
- Check has_been_set() when embedding zeroclaw in a larger process
- Prefer the try_* variants in shared processes and test harnesses
- Grep dependencies for fmt::init()/set_global_default when this panic appears
When it happens
Trigger: Calling install_global_subscriber a second time, or calling it after anything else installed a global subscriber: tracing_subscriber::fmt::init() in another crate or test harness, env_logger's tracing bridge, or an embedding application that sets its own default.
Common situations: Integration test suites where an earlier test initialized logging; a dependency that calls init() itself; embedding zeroclaw in a host app that already configures tracing; a refactor that moves the install call onto a path executed more than once (e.g. per-agent instead of per-process).
Related errors
- purge_agent not supported by this memory backend
- rename_agent not supported by this memory backend
- memory backend '{}' does not support agent-attributed StoreO
- live model listing is not supported for this model_provider
- ModelProvider returned non-prompt-guided tools payload ({pay
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/c755489a13a08e21.
Report an issue: GitHub.