{"record":{"id":"69ca845a9008d2a9","repo":"zeroclaw-labs/zeroclaw","slug":"qdrant-search-failed-status-text","errorCode":null,"errorMessage":"Qdrant search failed ({status}): {text}","messagePattern":"Qdrant search failed \\((.+?)\\): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-memory/src/qdrant.rs","lineNumber":645,"sourceCode":"\n        if let Some(f) = filter {\n            search_body[\"filter\"] = f;\n        }\n\n        let resp = self\n            .request(\n                reqwest::Method::POST,\n                &format!(\"/collections/{}/points/search\", self.collection),\n            )\n            .json(&search_body)\n            .send()\n            .await\n            .context(\"failed to search Qdrant\")?;\n\n        if !resp.status().is_success() {\n            let status = resp.status();\n            let text = resp.text().await.unwrap_or_default();\n            anyhow::bail!(\"Qdrant search failed ({status}): {text}\");\n        }\n\n        let result: QdrantSearchResult = resp.json().await?;\n\n        let mut entries: Vec<MemoryEntry> = result\n            .result\n            .into_iter()\n            .filter_map(|point| {\n                let payload = point.payload?;\n                let id = match &point.id {\n                    serde_json::Value::String(s) => s.clone(),\n                    serde_json::Value::Number(n) => n.to_string(),\n                    _ => return None,\n                };\n\n                Some(MemoryEntry {\n                    id,\n                    key: payload.key,","sourceCodeStart":627,"sourceCodeEnd":663,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-memory/src/qdrant.rs#L627-L663","documentation":"recall() embeds the query and POSTs /collections/{c}/points/search; a non-2xx response raises this error with the status and body. The search body carries the query vector, so Qdrant validates its dimension against the collection schema on every call.","triggerScenarios":"400 'vector dimension mismatch' after the embedding provider changed (collection was created with the old model's dimensions); 404 collection missing; 401/403 key issues; 5xx overload.","commonSituations":"Switching the memory model_provider (e.g., 1536-dim OpenAI vs 384-dim local model) without recreating the Qdrant collection, after which every recall fails; Qdrant upgrades tightening search payload validation.","solutions":["Compare dimensions: GET /collections/{c} -> result.config.params.vectors.size vs the provider's dims; if they differ, export memories, recreate the collection under a new name (restart so ensure_collection rebuilds it) and re-embed","Keep one collection per embedding model, or move to a new collection name when changing models","401/403: fix the api-key; 5xx: retry once Qdrant is ready","If dimensions match and it still 400s, read the Qdrant body text in the message for the exact rejected field"],"exampleFix":"# before\n[memory]\nmodel_provider = \"openai\"   # 1536 dims; collection was built for a 384-dim model\n\n# after: give the new model its own collection and restart so ensure_collection rebuilds it\n[memory.qdrant]\ncollection = \"zeroclaw-memory-openai\"","handlingStrategy":"try-catch","validationCode":"// Compare embedder dims to the collection schema before recall\nlet info: serde_json::Value = client.get(format!(\"{url}/collections/{c}\")).send().await?.json().await?;\nlet col_dims = info.pointer(\"/result/config/params/vectors/size\").and_then(|v| v.as_u64());\nif col_dims != Some(embedder_dims as u64) { /* recreate/migrate collection before recalling */ }","typeGuard":"fn is_qdrant_search_error(e: &anyhow::Error) -> bool {\n    e.to_string().starts_with(\"Qdrant search failed\")\n}","tryCatchPattern":"match memory.recall(q, limit).await {\n    Ok(entries) => entries,\n    Err(e) if is_qdrant_search_error(&e) => vec![], // degrade to no memories; page the operator\n    Err(e) => return Err(e),\n}","preventionTips":["Pin one embedding model per Qdrant collection; use a new collection name when switching","Export memories before changing embedding providers","Compare collection vector size against embedder dimensions during startup checks"],"tags":["qdrant","vector-search","embedding-dimensions","http-status","rust"],"backgroundTag":"vector-dimension-mismatch","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}