zeroclaw-labs/zeroclaw · error
Qdrant scroll failed during migration ({status}): {text}
Error message
Qdrant scroll failed during migration ({status}): {text} What it means
After ensuring the collection, QdrantMemory::migrate_session_ids_to_sanitized pages through every point (POST /collections/{c}/points/scroll, limit 1000, following next_page_offset) to find session_id payloads that need rewriting. This error means one of those scroll pages returned non-2xx; the migration runs inside new()/ensure_initialized() on every startup while the embedder reports non-zero dimensions.
Source
Thrown at crates/zeroclaw-memory/src/qdrant.rs:316
});
if let Some(ref offset) = next_offset {
scroll_body["offset"] = offset.clone();
}
let resp = self
.request(
reqwest::Method::POST,
&format!("/collections/{}/points/scroll", self.collection),
)
.json(&scroll_body)
.send()
.await
.context("failed to scroll Qdrant for session_id migration")?;
if !resp.status().is_success() {
let status = resp.status();
let text = resp.text().await.unwrap_or_default();
anyhow::bail!("Qdrant scroll failed during migration ({status}): {text}");
}
let page: QdrantScrollResult = resp.json().await?;
for point in &page.result.points {
if let Some(ref payload) = point.payload
&& let Some(ref sid) = payload.session_id
{
seen.insert(sid.clone());
}
}
match page.result.next_page_offset {
Some(offset) if !offset.is_null() => next_offset = Some(offset),
_ => break,
}
}
let mut rewritten = 0usize;View on GitHub (pinned to 88bb9c8533)
Solutions
- Read the status in the message: 429 means back off and retry — lazy init re-runs the migration on the next operation after a restart
- 404 means the collection vanished; recreate it (restart the process so ensure_collection runs) and restore from backup if needed
- 5xx/504 means Qdrant is unhealthy or the proxy timed out: check GET /readyz and raise proxy read timeouts for scroll endpoints
- Retry startup; the migration is idempotent and rescans from scratch each run
Defensive patterns
Strategy: retry
Validate before calling
// Gate startup on Qdrant health and collection presence before first memory op
let ready = client.get(format!("{url}/readyz")).send().await?.status().is_success();
let exists = client.get(format!("{url}/collections/{collection}")).send().await?.status().is_success(); Type guard
fn is_migration_scroll_error(e: &anyhow::Error) -> bool {
e.to_string().starts_with("Qdrant scroll failed during migration")
} Try / catch
if let Err(e) = memory.get("warmup").await {
if is_migration_scroll_error(&e) { /* back off, restart op; init retries lazily */ }
} Prevention
- Stagger multi-instance restarts so only one runs the session_id migration
- Gate boot on GET /readyz
- Keep reverse-proxy read timeouts generous for /points/scroll
- Avoid dropping/recreating collections while agents boot
When it happens
Trigger: Collection deleted or renamed out-of-band between creation and the scroll; 429 rate limiting on Qdrant Cloud while scrolling a large collection; 400 from a stale/invalid offset after a Qdrant version change; 502/504 from a reverse proxy timing out on a large page.
Common situations: Qdrant Cloud free tier with a large memory collection whose scroll bursts trip rate limits; someone dropping/recreating collections while agents restart; Nginx/Traefik in front of Qdrant with a low proxy_read_timeout on /points/scroll.
Related errors
- Qdrant collection creation failed ({status}): {text}
- Qdrant set payload failed during migration ({status}): {text
- purge_agent not supported by this memory backend
- Qdrant scroll failed ({status}): {text}
- Qdrant set payload failed ({status}): {text}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/c2e5459d97dcc567.
Report an issue: GitHub.