apache/seatunnel · error · IllegalArgumentException

Stripe option 'rate_limit_backoff_ms' must not be negative

Error message

Stripe option 'rate_limit_backoff_ms' must not be negative

What it means

buildWithConfig validates the rate_limit_backoff_ms option, the base delay in milliseconds between Stripe 429 retry attempts. Negative delays are nonsensical, so the connector throws this IllegalArgumentException during config validation.

Solutions

  1. Set rate_limit_backoff_ms to a non-negative value (e.g. 1000).
  2. Remove the option to use the default backoff.
  3. If retries feel too slow, lower the positive value rather than making it negative.
  4. Validate related rate_limit_max_retries is also non-negative so the pair is consistent.

Example fix

// before
rate_limit_backoff_ms = -500
// after
rate_limit_backoff_ms = 1000
Defensive patterns

Strategy: validation

Validate before calling

long backoff = pluginConfig.get(StripeSourceOptions.RATE_LIMIT_BACKOFF_MS);
if (backoff < 0) {
    throw new IllegalArgumentException("rate_limit_backoff_ms must be >= 0");
}

Try / catch

try {
    StripeSourceParameter p = StripeSourceParameter.buildWithConfig(pluginConfig);
} catch (IllegalArgumentException e) {
    throw new IllegalArgumentException("Invalid rate_limit_backoff_ms: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: Calling buildWithConfig with pluginConfig where RATE_LIMIT_BACKOFF_MS resolves to a negative long, e.g. rate_limit_backoff_ms = -500.

Common situations: User tries to speed up polling with a negative value; sign typo; misreading the option as a relative adjustment rather than an absolute delay.

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 apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/35db86eeafc1d720. Report an issue: GitHub.

Appendix: source

Thrown at seatunnel-connectors-v2/connector-http/connector-http-stripe/src/main/java/org/apache/seatunnel/connectors/seatunnel/stripe/source/config/StripeSourceParameter.java:79

        if (createdGte != null && createdGte < 0) {
            throw new IllegalArgumentException("Stripe option 'created_gte' must not be negative");
        }
        if (createdLt != null && createdLt < 0) {
            throw new IllegalArgumentException("Stripe option 'created_lt' must not be negative");
        }
        if (createdGte != null && createdLt != null && createdGte >= createdLt) {
            throw new IllegalArgumentException(
                    "Stripe option 'created_gte' must be less than 'created_lt'");
        }

        this.rateLimitMaxRetries = pluginConfig.get(StripeSourceOptions.RATE_LIMIT_MAX_RETRIES);
        this.rateLimitBackoffMs = pluginConfig.get(StripeSourceOptions.RATE_LIMIT_BACKOFF_MS);
        if (rateLimitMaxRetries < 0) {
            throw new IllegalArgumentException(
                    "Stripe option 'rate_limit_max_retries' must not be negative");
        }
        if (rateLimitBackoffMs < 0) {
            throw new IllegalArgumentException(
                    "Stripe option 'rate_limit_backoff_ms' must not be negative");
        }

        setUrl(trimTrailingSlash(apiBaseUrl.trim()) + PAYMENT_INTENTS_PATH);
        setMethod(HttpRequestMethod.GET);

        Map<String, String> requestHeaders = new LinkedHashMap<>();
        requestHeaders.put(AUTHORIZATION, "Bearer " + secretKey);
        requestHeaders.put(ACCEPT, "application/json");
        pluginConfig
                .getOptional(StripeSourceOptions.API_VERSION)
                .filter(version -> !version.trim().isEmpty())
                .ifPresent(version -> requestHeaders.put(STRIPE_VERSION, version.trim()));
        setHeaders(requestHeaders);

        Map<String, String> requestParams = new LinkedHashMap<>();
        requestParams.put("limit", Integer.toString(pageSize));
        if (createdGte != null) {

View on GitHub (pinned to cf67b549a7)