vectordotdev/vector · info

Should never end

Error message

Should never end

What it means

This panic fires in the health-check service's `poll_ready` when an endpoint fails probation and the circuit opens, but `backoff.next()` returns `None`. Vector's `ExponentialBackoff` is configured with `max_attempts: None` (unlimited), so the iterator never ends; the expect asserts that invariant.

Solutions

  1. Report as a bug to Vector if observed.
  2. Verify no custom build constrains the health backoff's max attempts.
Defensive patterns

Strategy: fallback

Prevention

When it happens

Trigger: An endpoint fails its health probation period and the service transitions to `CircuitState::Open`; panic requires the backoff iterator to be exhausted, which the unlimited-attempts configuration prevents.

Common situations: Not reachable with default configuration; could only appear if the health service's backoff were constructed with a bounded attempt count.

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


AI-assisted analysis of vectordotdev/vector@bdb87aeaa4 (2026-09-16). Data as JSON: /api/errors/24c6992d74224bd4. Report an issue: GitHub.

Appendix: source

Thrown at src/sinks/util/service/health.rs:182

                CircuitState::HalfOpen {
                    permit: None,
                    ref mut done,
                } => {
                    let done = Pin::new(done);
                    ready!(done.poll(cx));

                    if self.counters.healthy(self.snapshot).is_ok() {
                        // A healthy response was observed
                        info!(message = "Endpoint is healthy.", endpoint = %&self.endpoint);

                        self.backoff.reset();
                        self.open.clone().open(emit_active_endpoints);
                        CircuitState::Closed
                    } else {
                        debug!(message = "Endpoint failed probation.", endpoint = %&self.endpoint);

                        CircuitState::Open(
                            sleep(self.backoff.next().expect("Should never end")).boxed(),
                        )
                    }
                }
                CircuitState::Closed => {
                    // Check for errors
                    match self.counters.healthy(self.snapshot) {
                        Ok(snapshot) => {
                            // Healthy
                            self.snapshot = snapshot;
                            return self.inner.poll_ready(cx).map_err(Into::into);
                        }
                        Err(errors) if errors >= UNHEALTHY_AMOUNT_OF_ERRORS => {
                            // Unhealthy
                            warn!(message = "Endpoint is unhealthy.", endpoint = %&self.endpoint);
                            CircuitState::Open(
                                sleep(self.backoff.next().expect("Should never end")).boxed(),
                            )
                        }

View on GitHub (pinned to bdb87aeaa4)