zeroclaw-labs/zeroclaw · error
Qdrant scroll failed ({status}): {text}
Error message
Qdrant scroll failed ({status}): {text} What it means
A paginated Qdrant scroll (POST /collections/{name}/points/scroll with an agent-id filter) returned a non-success HTTP status; the status code and response body are surfaced verbatim. This scroll backs purge_agent, export_agent, rename_agent, count_agent, and recall_for_agents, so any of those agent-scoped operations can surface it.
Source
Thrown at crates/zeroclaw-memory/src/qdrant.rs:173
"limit": 1000,
"with_payload": true,
"filter": { "must": must_conditions }
});
let resp = self
.request(
reqwest::Method::POST,
&format!("/collections/{}/points/scroll", self.collection),
)
.json(&scroll_body)
.send()
.await
.context("failed to scroll Qdrant for allowed agent set")?;
if !resp.status().is_success() {
let status = resp.status();
let text = resp.text().await.unwrap_or_default();
anyhow::bail!("Qdrant scroll failed ({status}): {text}");
}
let result: QdrantScrollResult = resp.json().await?;
let entries = result
.result
.points
.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,View on GitHub (pinned to 88bb9c8533)
Solutions
- Read the status and body: 401/403 means credentials in [storage.qdrant.<alias>], 404 means the collection is gone, 400 usually means collection-name or filter shape, 5xx is server-side.
- Verify url, api_key, and collection still match the live cluster.
- Retry transient 5xx after a short backoff; re-create the collection (ensure_collection runs on init) if it was deleted.
Example fix
# diagnose against the same cluster
$ curl -H "api-key: $QDRANT_KEY" \
http://qdrant-host:6333/collections/zeroclaw_memories/points/scroll \
-X POST -H 'Content-Type: application/json' \
-d '{"limit": 1, "with_payload": true}' Defensive patterns
Strategy: try-catch
Try / catch
match memory.recall_for_agents(query, limit, &agents).await {
Ok(v) => Ok(v),
Err(e) => {
let msg = e.to_string();
if msg.contains("Qdrant scroll failed (401") || msg.contains("Qdrant scroll failed (403") {
return Err(e.context("qdrant credentials rejected; fix [storage.qdrant.<alias>].api_key"));
}
if msg.contains("Qdrant scroll failed (404") {
return Err(e.context("qdrant collection missing; recreate it via ensure_initialized"));
}
if msg.contains("Qdrant scroll failed (5") {
// server-side: safe to retry with backoff
}
Err(e)
}
} Prevention
- Alert on scroll error rates per status class so key rotation and dropped collections are caught early.
- Keep the collection name stable; if it must be recreated, do it while the service is not mid-operation and let ensure_collection rebuild it on restart.
When it happens
Trigger: Qdrant answers 401/403 (bad or rotated API key), 404 (collection dropped mid-operation), 400 (malformed filter or invalid collection name), or 5xx while the scroll executes. Transport-level failures surface as a different context error; this one means Qdrant answered with an error status.
Common situations: Expired Qdrant API key; collection recreated without the expected payload; Qdrant restarts or cloud maintenance windows during long scrolls; the collection deleted by another operator between check and scroll.
Related errors
- Qdrant scroll failed ({status}): {text}
- Qdrant set payload failed ({status}): {text}
- Qdrant collection check failed ({status}): {text}
- Qdrant connection failed: {e}
- Qdrant scroll failed during migration ({status}): {text}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/03e40032eb8778be.
Report an issue: GitHub.