quickwit-oss/quickwit · error
request should be set
Error message
request should be set
What it means
This `.expect("request should be set")` panic fires in `EventListener::poll` (quickwit-common/src/tower/event_listener.rs). The tower `Service` contract requires `poll_ready` to be called (and return Ready) before each `call`; `call` stores the request so that after the inner future resolves successfully, an event can be published for it. The panic means the future was polled after the request was already taken, or `call` was never invoked properly through the service stack — a violation of the tower protocol by the caller or a middleware above.
Source
Thrown at quickwit/quickwit-common/src/tower/event_listener.rs:103
inner: F,
event_broker: EventBroker,
request: Option<R>,
}
impl<R, F, T, E> Future for ResponseFuture<F, R>
where
R: Event,
F: Future<Output = Result<T, E>>,
{
type Output = Result<T, E>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
let response = ready!(this.inner.poll(cx));
if response.is_ok() {
this.event_broker
.publish(this.request.take().expect("request should be set"));
}
Poll::Ready(Ok(response?))
}
}
#[cfg(test)]
mod tests {
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::Duration;
use async_trait::async_trait;
use super::*;
use crate::pubsub::EventSubscriber;
#[derive(Debug, Clone, Copy)]
struct MyEvent {View on GitHub (pinned to a39730c5cd)
Solutions
- Ensure every request goes through the tower protocol: call `poll_ready` (or `.ready().await`) and wait for `Poll::Ready(Ok(()))` before each `call`.
- Use `tower::ServiceExt::oneshot(service, request)` or `service.ready().await?.call(req)` instead of calling `call` directly.
- Do not poll the returned future after it has resolved; drop it after completion.
- If a custom layer wraps this service, verify it does not clone or double-poll inner futures and forwards `poll_ready` correctly.
Example fix
// before: calling without readiness let fut = service.call(request); let res = fut.await; // after: follow the tower protocol use tower::ServiceExt; let response = service.ready().await?.call(request).await?;
Defensive patterns
Strategy: type-guard
Validate before calling
// Always route requests through readiness-aware helpers use tower::ServiceExt; // let response = event_listener_service.ready().await?.call(req).await?;
Type guard
// Only issue a call when the service is ready
fn is_ready<S: tower::Service<R>, R>(svc: &mut S, cx: &mut std::task::Context<'_>) -> bool {
use tower::Service;
matches!(svc.poll_ready(cx), std::task::Poll::Ready(Ok(())))
} Try / catch
// Panics here indicate a protocol bug; catch at the server boundary in tests
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
// drive the service via oneshot
tower::ServiceExt::oneshot(&mut svc, req)
})); Prevention
- Never call `call` directly; use ServiceExt::ready/oneshot.
- Never poll a response future after it has completed.
- When writing middleware, always forward poll_ready and respect its result.
- Avoid caching/cloning inner futures across polls.
When it happens
Trigger: Polling the response future returned by `EventListener::call` more times than allowed after completion, calling `call` without a prior successful `poll_ready` such that the request slot handling is desynchronized, or a custom wrapper that clones/caches the future and polls it twice.
Common situations: Hand-written tower middleware or load-balancing layers that violate the poll_ready/call contract; code that collects service futures and re-polls them; custom service implementations built on quickwit's event listener layer that bypass `ServiceExt::ready()`.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- `poll_ready` should be called before `call`
- lock should not be poisoned
- node not found in pending
- OTP logs or traces do not support VRL transforms
- `doc_batch` should not be empty
AI-assisted analysis of quickwit-oss/quickwit@a39730c5cd (2026-09-08).
Data as JSON: /api/errors/13dcae15a48a2864.
Report an issue: GitHub.