apereo/cas · warning

The request is throttled as capacity is entirely consumed…

Error message

The request is throttled as capacity is entirely consumed. Available tokens are [{}]

What it means

This WARN indicates the rate-limit bucket is exhausted: bucket.tryConsume returned false, so the request is throttled. CAS computes a Retry-After value from the bucket refill probe and returns a BucketConsumptionResult with consumed=false plus X-Rate-Limit headers.

Solutions

  1. Tune capacity/refill settings (e.g. cas.authn.throttle capacity and refill duration) to match legitimate traffic.
  2. Verify the bucket key granularity so distinct users/clients are not throttled collectively.
  3. If the client is yours, add backoff honoring the returned retryAfterSeconds / X-Rate-Limit-Retry-After-Seconds header.
  4. Check for abusive traffic sources and block them upstream.

Example fix

// before
cas.authn.throttle.capacity=10
cas.authn.throttle.refill-duration=PT1H
// after
cas.authn.throttle.capacity=100
cas.authn.throttle.refill-duration=PT1M
Defensive patterns

Strategy: retry

Validate before calling

// client-side: check remaining tokens before next call
const remaining = Number(response.headers['x-rate-limit-remaining']);
if (remaining === 0) await sleep(Number(response.headers['x-rate-limit-retry-after-seconds']) * 1000);

Try / catch

BucketConsumptionResult r = bucketConsumer.consume(key);
if (!r.isConsumed()) {
  long wait = r.getRetryAfterSeconds();
  Thread.sleep(TimeUnit.SECONDS.toMillis(wait));
  r = bucketConsumer.consume(key);
}

Prevention

When it happens

Trigger: consume() is called when all tokens in the bucket are already consumed (canProceed is false); happens on every request once the allowed rate is exceeded within the refill window.

Common situations: Client retry storms or brute-force attempts exhausting the throttle budget; overly aggressive rate-limit configuration (small capacity, long refill period); shared buckets keyed too broadly (e.g. same key for all users behind one proxy IP).

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/a938eea5aa948c0b. Report an issue: GitHub.

Appendix: source

Thrown at support/cas-server-support-bucket4j-core/src/main/java/org/apereo/cas/bucket4j/consumer/DefaultBucketConsumer.java:56

            val canProceed = FunctionUtils.doAndHandle(() -> {
                if (properties.isBlocking()) {
                    LOGGER.debug("Attempting to consume a token for the authentication attempt");
                    return bucket.tryConsume(1, MAX_WAIT_NANOS, BlockingStrategy.PARKING);
                }
                return bucket.tryConsume(1);
            }, e -> {
                LoggingUtils.error(LOGGER, e);
                Thread.currentThread().interrupt();
                return false;
            }).get();

            val headers = new LinkedHashMap<String, String>();
            val availableTokens = bucket.getAvailableTokens();
            if (!canProceed) {
                val probe = bucket.tryConsumeAndReturnRemaining(1);
                val seconds = TimeUnit.NANOSECONDS.toSeconds(probe.getNanosToWaitForRefill());
                headers.put(HEADER_NAME_X_RATE_LIMIT_RETRY_AFTER_SECONDS, Long.toString(seconds));
                LOGGER.warn("The request is throttled as capacity is entirely consumed. Available tokens are [{}]", availableTokens);
                return BucketConsumptionResult.builder()
                    .retryAfterSeconds(seconds)
                    .tokensRemaining(availableTokens)
                    .consumed(false).headers(headers).build();
            }
            headers.put(HEADER_NAME_X_RATE_LIMIT_REMAINING, Long.toString(availableTokens));
            return BucketConsumptionResult.builder()
                .tokensRemaining(availableTokens)
                .consumed(true).headers(headers).build();
        });
    }
}

View on GitHub (pinned to e7288fc434)