{"record":{"id":"e985ca8f882d35d0","repo":"zeroclaw-labs/zeroclaw","slug":"memory-backend-references-a-storage-alias-co","errorCode":null,"errorMessage":"memory backend {:?} references a storage alias; construct memory from the full Config so the selected alias is applied","messagePattern":"memory backend (.+?) references a storage alias; construct memory from the full Config so the selected alias is applied","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-memory/src/lib.rs","lineNumber":491,"sourceCode":"            api_key: explicit_api_key.or(inherited_api_key),\n        };\n    };\n\n    ResolvedEmbeddingConfig {\n        model_provider: concrete_provider,\n        model,\n        dimensions,\n        api_key: explicit_api_key.or(provider_key).or(inherited_api_key),\n    }\n}\n\npub fn create_memory(\n    config: &MemoryConfig,\n    workspace_dir: &Path,\n    api_key: Option<&str>,\n) -> anyhow::Result<Box<dyn Memory>> {\n    if config.backend.trim().contains('.') {\n        anyhow::bail!(\n            \"memory backend {:?} references a storage alias; construct memory from the full Config so the selected alias is applied\",\n            config.backend\n        );\n    }\n\n    create_memory_with_storage_and_routes(\n        config,\n        &[],\n        ActiveStorage::None,\n        workspace_dir,\n        api_key,\n        None,\n    )\n}\n\n/// Construct memory from the canonical loaded configuration.\n///\n/// Config-aware production paths should use this entrypoint so the selected","sourceCodeStart":473,"sourceCodeEnd":509,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-memory/src/lib.rs#L473-L509","documentation":"create_memory receives only a MemoryConfig. When memory.backend contains a dot (e.g. \"qdrant.prod\", \"postgres.main\"), the suffix is a storage alias that must be looked up in the full Config's [storage.*] sections, which this function does not have. It fails fast instead of silently dropping the alias and connecting to an arbitrary or default storage.","triggerScenarios":"Passing a MemoryConfig whose backend is in alias (dotted) form to create_memory — commonly after extracting config.memory out of the full Config, or after constructing a MemoryConfig inline from operator docs that show dotted backend examples.","commonSituations":"Callers holding only the memory section of the config; tests that build MemoryConfig by hand and paste a dotted backend string; refactors that split Config and lose the storage half.","solutions":["Call create_memory_from_config (or create_memory_with_storage_and_routes) with the full Config so the alias resolves against [storage.*].","If you only have a MemoryConfig by design, strip the alias and use a plain backend name (\"sqlite\", \"lucid\", \"markdown\")."],"exampleFix":"// before — config.memory.backend == \"qdrant.prod\"\nlet mem = create_memory(&config.memory, workspace_dir, api_key)?;\n\n// after\nlet mem = create_memory_from_config(&config, api_key)?;","handlingStrategy":"type-guard","validationCode":"if config.memory.backend.trim().contains('.') {\n    anyhow::bail!(\n        \"backend {:?} uses a storage alias; construct from the full Config\",\n        config.memory.backend\n    );\n}","typeGuard":"fn backend_needs_full_config(backend: &str) -> bool {\n    backend.trim().contains('.')\n}","tryCatchPattern":null,"preventionTips":["Default to create_memory_from_config everywhere; reserve create_memory for code that controls the backend string and keeps it alias-free.","Lint configs at load time: any memory.backend containing '.' must be paired with a matching [storage.<family>.<alias>] section."],"tags":["config","storage-alias","api-misuse","memory-backend"],"backgroundTag":"invalid-config-value","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}