quickwit-oss/quickwit · info

60 should be non-zero

Error message

60 should be non-zero

What it means

The serve startup creates an SMA rate estimator with 60 buckets for ingest rate tracking. The bucket count 60 is a hardcoded literal, and NonZeroUsize::new(60).expect documents the invariant that it is non-zero. This can only panic if the literal is refactored to a runtime value of 0.

Source

Thrown at quickwit/quickwit-serve/src/lib.rs:379

) -> anyhow::Result<IngestServiceClient> {
    if disable_ingest_v1() {
        debug!("returning no-op ingest service because ingest v1 is disabled");
        let (balance_channel, _change_tx) = BalanceChannel::new();
        let ingest_service = IngestServiceClient::from_balance_channel(
            balance_channel,
            node_config.grpc_config.max_message_size,
            node_config.ingest_api_config.grpc_compression_encoding(),
        );
        return Ok(ingest_service);
    }
    if node_config.is_service_enabled(QuickwitService::Indexer) {
        let ingest_api_service = start_ingest_api_service(
            universe,
            &node_config.data_dir_path,
            &node_config.ingest_api_config,
        )
        .await?;
        let num_buckets = NonZeroUsize::new(60).expect("60 should be non-zero");
        let rate_estimator = SmaRateEstimator::new(
            num_buckets,
            Duration::from_secs(10),
            Duration::from_millis(100),
        );
        let memory_capacity = ingest_api_service.ask(GetMemoryCapacity).await?;
        let min_rate = ConstantRate::new(ByteSize::mib(1).as_u64(), Duration::from_millis(100));
        let rate_modulator = RateModulator::new(rate_estimator.clone(), memory_capacity, min_rate);
        let ingest_service = IngestServiceClient::tower()
            .stack_ingest_layer(
                ServiceBuilder::new()
                    .layer(EstimateRateLayer::<IngestRequest, _>::new(rate_estimator))
                    .layer(BufferLayer::new(100))
                    .layer(RateLimitLayer::new(rate_modulator))
                    .into_inner(),
            )
            .build_from_mailbox(ingest_api_service);
        Ok(ingest_service)

View on GitHub (pinned to a39730c5cd)

Solutions

  1. No action needed; it is a compile-time-safe assertion
  2. If making the bucket count configurable, validate it is > 0 in config parsing

Example fix

// before
let num_buckets = NonZeroUsize::new(60).expect("60 should be non-zero");
// after
let num_buckets = NonZeroUsize::new(node_config.ingest_api_config.rate_estimator_buckets)
    .ok_or_else(|| anyhow::anyhow!("rate_estimator_buckets must be non-zero"))?;
Defensive patterns

Strategy: validation

Validate before calling

// If bucket count becomes configurable, validate at config load:
if buckets == 0 { return Err(anyhow!("ingest rate estimator buckets must be > 0")); }

Type guard

fn valid_buckets(n: usize) -> bool { n > 0 }

Prevention

When it happens

Trigger: Only reachable if the hardcoded 60 is replaced by a configurable/derived value that evaluates to zero; as written it can never fire.

Common situations: Refactoring the ingest rate estimator to make bucket count configurable without guarding against 0.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of quickwit-oss/quickwit@a39730c5cd (2026-09-08). Data as JSON: /api/errors/70f136051b66613e. Report an issue: GitHub.