apache/beam · error · IllegalArgumentException

EnvoyRateLimiterFactory requires EnvoyRateLimiterContext

Error message

EnvoyRateLimiterFactory requires EnvoyRateLimiterContext

What it means

EnvoyRateLimiterFactory.getLimiter(context) only accepts a RateLimiterContext that is an instance of EnvoyRateLimiterContext; any other context implementation is rejected with IllegalArgumentException. The factory needs Envoy-specific data (like descriptors) that a generic context does not carry.

Source

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

    }
    synchronized (this) {
      if (stub == null) {
        RateLimiterClientCache cache = RateLimiterClientCache.getOrCreate(options.getAddress());
        this.clientCache = cache;
        stub = RateLimitServiceGrpc.newBlockingStub(cache.getChannel());
      }
    }
  }

  @VisibleForTesting
  void setStub(RateLimitServiceGrpc.RateLimitServiceBlockingStub stub) {
    this.stub = stub;
  }

  @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;

View on GitHub (pinned to 12126d8942)

Solutions

  1. Construct an EnvoyRateLimiterContext (via its builder) and pass that to getLimiter().
  2. Use the matching factory for the context type you have, or a factory that accepts generic contexts.
  3. Check the context's runtime class (instanceof EnvoyRateLimiterContext) before wiring it into this factory.

Example fix

// before
RateLimiter limiter = envoyFactory.getLimiter(genericContext); // throws
// after
EnvoyRateLimiterContext ctx = EnvoyRateLimiterContext.builder().setDescriptors(descriptors).build();
RateLimiter limiter = envoyFactory.getLimiter(ctx);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(ctx instanceof EnvoyRateLimiterContext)) {
  throw new IllegalArgumentException("build EnvoyRateLimiterContext for EnvoyRateLimiterFactory");
}

Type guard

static boolean isEnvoyContext(RateLimiterContext ctx) {
  return ctx instanceof EnvoyRateLimiterContext;
}

Try / catch

try {
  RateLimiter limiter = factory.getLimiter(ctx);
} catch (IllegalArgumentException e) {
  ctx = EnvoyRateLimiterContext.builder().setDescriptors(descriptors).build();
  RateLimiter limiter = factory.getLimiter(ctx);
}

Prevention

When it happens

Trigger: Passing a RateLimiterContext created by another factory (or a plain/default context implementation) into EnvoyRateLimiterFactory.getLimiter().

Common situations: Mixing rate limiter factories and contexts in configuration (e.g. a generic context built for a different backend), or after refactoring/swapping the limiter implementation while reusing old context objects.

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/a5e617e40182d28d. Report an issue: GitHub.