apache/beam · error · IllegalArgumentException

EnvoyRateLimiterFactory requires EnvoyRateLimiterContext, go

Error message

EnvoyRateLimiterFactory requires EnvoyRateLimiterContext, got: 

What it means

EnvoyRateLimiterFactory.allow(context, permits) checks that the supplied RateLimiterContext is an EnvoyRateLimiterContext and, if not, throws IllegalArgumentException including the offending context's class name. Unlike getLimiter, this variant is called per-request on the hot path, so the check runs on every allow() invocation.

Source

Thrown at sdks/java/io/components/src/main/java/org/apache/beam/sdk/io/components/ratelimiter/EnvoyRateLimiterFactory.java:121

  }

  @Override
  public RateLimiter getLimiter(RateLimiterContext context) {
    if (!(context instanceof EnvoyRateLimiterContext)) {
      throw new IllegalArgumentException(
          "EnvoyRateLimiterFactory requires EnvoyRateLimiterContext");
    }
    return new EnvoyRateLimiter(this, (EnvoyRateLimiterContext) context);
  }

  @Override
  public boolean allow(RateLimiterContext context, int permits)
      throws IOException, InterruptedException {
    if (permits == 0) {
      return true;
    }
    if (!(context instanceof EnvoyRateLimiterContext)) {
      throw new IllegalArgumentException(
          "EnvoyRateLimiterFactory requires EnvoyRateLimiterContext, got: "
              + context.getClass().getName());
    }
    checkArgument(permits >= 0, "Permits must be non-negative");
    EnvoyRateLimiterContext envoyContext = (EnvoyRateLimiterContext) context;
    return fetchTokens(envoyContext, permits);
  }

  private boolean fetchTokens(EnvoyRateLimiterContext context, int tokens)
      throws IOException, InterruptedException {

    init();
    RateLimitServiceGrpc.RateLimitServiceBlockingStub currentStub = stub;
    if (currentStub == null) {
      throw new IllegalStateException("RateLimitServiceStub is null");
    }

    Map<String, String> descriptors = context.getDescriptors();

View on GitHub (pinned to 12126d8942)

Solutions

  1. Pass an EnvoyRateLimiterContext (built with the required descriptors) to allow().
  2. Use EnvoyRateLimiterFactory.getLimiter(context) once to obtain a RateLimiter instead of calling allow() with raw contexts.
  3. The error message includes the actual class name — confirm which implementation is being constructed upstream and fix it at the source.

Example fix

// before
boolean ok = envoyFactory.allow(RateLimiterContext.create(), 1); // throws
// after
boolean ok = envoyFactory.allow(EnvoyRateLimiterContext.builder().setDescriptors(d).build(), 1);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(ctx instanceof EnvoyRateLimiterContext)) {
  throw new IllegalArgumentException("allow() requires EnvoyRateLimiterContext, got " + ctx.getClass().getName());
}

Type guard

static EnvoyRateLimiterContext asEnvoyContext(RateLimiterContext ctx) {
  return ctx instanceof EnvoyRateLimiterContext ? (EnvoyRateLimiterContext) ctx : null;
}

Try / catch

try {
  allowed = factory.allow(ctx, permits);
} catch (IllegalArgumentException e) {
  LOG.error("Wrong context type: {}", e.getMessage()); // includes offending class name
}

Prevention

When it happens

Trigger: Calling allow() with a non-Envoy RateLimiterContext implementation, e.g. one produced by a different RateLimiterFactory or a hand-rolled subclass of RateLimiterContext.

Common situations: Shared rate-limiter plumbing that passes a generic context to whichever factory is configured; swapping the factory to Envoy without changing the context construction code.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/21e39999ce0b14ab. Report an issue: GitHub.