languagetool-org/languagetool · warning · TooManyRequestsException
IP request size limit of bytes per seconds exceeded
Error message
IP request size limit of bytes per seconds exceeded
What it means
Outside TEXTLEVEL_ONLY mode, RequestLimiter enforces a per-IP request-size quota. When total bytes from one IP exceed ipRequestLimitInBytes within requestLimitPeriodInSeconds, checkLimit throws TooManyRequestsException (HTTP 429). This caps aggregate upload volume per client IP for all check modes.
Solutions
- Pause until requestLimitPeriodInSeconds elapses, then resume slowly
- Implement exponential backoff on 429 and cap total bytes sent per IP per window
- Use Premium credentials for higher limits, or distribute calls across IPs
- Server admins: raise ipRequestLimitInBytes in HTTPServerConfig / launch arguments
- Batch and deduplicate texts before sending to reduce total bytes
Example fix
// before: immediate retry on 429
catch (e) { check(text); }
// after
catch (TooManyRequests/429 e) { sleep(backoff); backoff *= 2; retry(); } Defensive patterns
Strategy: retry
Validate before calling
function withinIpBudget(bytes) { return ipBytesWindow + bytes <= ipRequestLimitInBytes; } Try / catch
catch (err) {
if (err instanceof HttpError && err.status === 429) {
await sleep(backoffMs); backoffMs = Math.min(backoffMs * 2, MAX_BACKOFF);
return attempt();
}
throw err;
} Prevention
- Implement exponential backoff with jitter for 429 responses
- Deduplicate and batch texts to cut total uploaded bytes
- Route through authenticated accounts or multiple egress IPs if legitimately high-volume
- Tune ipRequestLimitInBytes on self-hosted deployments to match real usage
When it happens
Trigger: POSTing to /v2/check (any non-textLevelOnly mode) where cumulative bytes from the client IP exceed ipRequestLimitInBytes within requestLimitPeriodInSeconds and requestLimitInBytes > 0.
Common situations: Server-side integrations routing many users through one outbound IP; scheduled jobs re-uploading the same corpora; retries without backoff after a 429; tight ipRequestLimitInBytes in self-hosted config.
Related errors
- Client request size limit of bytes per seconds exceeded…
- Client request size limit of bytes per seconds exceeded
- IP request size limit of bytes per seconds exceeded in…
- Client request limit of requests per seconds exceeded
- IP request limit of requests per seconds exceeded
AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06).
Data as JSON: /api/errors/a46b81f5c2eb61f4.
Report an issue: GitHub.
Appendix: source
Thrown at languagetool-server/src/main/java/org/languagetool/server/RequestLimiter.java:245
if (ipFingerprintFactor > 0 && requestLimitInBytes > 0 && requestSizeByFingerprint > requestLimitInBytes) {
String msg = "limit in Mode.TEXTLEVEL_ONLY: " + requestLimitInBytes + " / " + requestLimitPeriodInSeconds + ", request size: " + requestSizeByIp + ", ip: " + ipAddress + ", fingerprint: " + fingerprint;
throw new TooManyRequestsException("Client request size limit of " + requestLimitInBytes + " bytes per " +
requestLimitPeriodInSeconds + " seconds exceeded in text-level checks");
}
if (requestLimitInBytes > 0 && requestSizeByIp > ipRequestLimitInBytes) {
String msg = "limit in Mode.TEXTLEVEL_ONLY: " + ipRequestLimitInBytes + " / " + requestLimitPeriodInSeconds + ", request size: " + requestSizeByIp + ", ip: " + ipAddress + ", fingerprint: " + fingerprint;
throw new TooManyRequestsException("IP request size limit of " + ipRequestLimitInBytes + " bytes per " +
requestLimitPeriodInSeconds + " seconds exceeded in text-level checks");
}
} else {
if (ipFingerprintFactor > 0 && requestLimitInBytes > 0 && requestSizeByFingerprint > requestLimitInBytes) {
String msg = "limit: " + requestLimitInBytes + " / " + requestLimitPeriodInSeconds + ", request size: " + requestSizeByIp + ", ip: " + ipAddress + ", fingerprint: " + fingerprint;
throw new TooManyRequestsException("Client request size limit of " + requestLimitInBytes + " bytes per " +
requestLimitPeriodInSeconds + " seconds exceeded");
}
if (requestLimitInBytes > 0 && requestSizeByIp > ipRequestLimitInBytes) {
String msg = "limit: " + ipRequestLimitInBytes + " / " + requestLimitPeriodInSeconds + ", request size: " + requestSizeByIp + ", ip: " + ipAddress + ", fingerprint: " + fingerprint;
throw new TooManyRequestsException("IP request size limit of " + ipRequestLimitInBytes + " bytes per " +
requestLimitPeriodInSeconds + " seconds exceeded");
}
}
}
}
}
protected static class RequestEvent {
private final String ip;
private final Date date;
private final int sizeInBytes;
private final String fingerprint;
private final JLanguageTool.Mode mode;
RequestEvent(String ip, Date date, int sizeInBytes, String fingerprint, JLanguageTool.Mode mode) {
this.ip = ip;
this.date = new Date(date.getTime());View on GitHub (pinned to 2e990059ce)