zeroclaw-labs/zeroclaw · error
Qdrant search failed ({status}): {text}
Error message
Qdrant search failed ({status}): {text} What it means
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.
Source
Thrown at crates/zeroclaw-memory/src/qdrant.rs:645
if let Some(f) = filter {
search_body["filter"] = f;
}
let resp = self
.request(
reqwest::Method::POST,
&format!("/collections/{}/points/search", self.collection),
)
.json(&search_body)
.send()
.await
.context("failed to search Qdrant")?;
if !resp.status().is_success() {
let status = resp.status();
let text = resp.text().await.unwrap_or_default();
anyhow::bail!("Qdrant search failed ({status}): {text}");
}
let result: QdrantSearchResult = resp.json().await?;
let mut entries: Vec<MemoryEntry> = result
.result
.into_iter()
.filter_map(|point| {
let payload = point.payload?;
let id = match &point.id {
serde_json::Value::String(s) => s.clone(),
serde_json::Value::Number(n) => n.to_string(),
_ => return None,
};
Some(MemoryEntry {
id,
key: payload.key,View on GitHub (pinned to 88bb9c8533)
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
Example fix
# before [memory] model_provider = "openai" # 1536 dims; collection was built for a 384-dim model # after: give the new model its own collection and restart so ensure_collection rebuilds it [memory.qdrant] collection = "zeroclaw-memory-openai"
Defensive patterns
Strategy: try-catch
Validate before calling
// Compare embedder dims to the collection schema before recall
let info: serde_json::Value = client.get(format!("{url}/collections/{c}")).send().await?.json().await?;
let col_dims = info.pointer("/result/config/params/vectors/size").and_then(|v| v.as_u64());
if col_dims != Some(embedder_dims as u64) { /* recreate/migrate collection before recalling */ } Type guard
fn is_qdrant_search_error(e: &anyhow::Error) -> bool {
e.to_string().starts_with("Qdrant search failed")
} Try / catch
match memory.recall(q, limit).await {
Ok(entries) => entries,
Err(e) if is_qdrant_search_error(&e) => vec![], // degrade to no memories; page the operator
Err(e) => return Err(e),
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Qdrant upsert failed ({status}): {text}
- Qdrant collection creation failed ({status}): {text}
- Qdrant delete failed ({status}): {text}
- Qdrant set payload failed during agent rename ({status}): {t
- Qdrant collection info failed ({status}): {text}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/69ca845a9008d2a9.
Report an issue: GitHub.