languagetool-org/languagetool · error · TooManyRequestsException
User request limit of per day exceeded. Try again after mid
Error message
User request limit of per day exceeded. Try again after midnight UTC.
What it means
HTTP 429 error thrown when an authenticated premium user has exceeded their configured maximum number of requests per day. The count comes from the database and the limit is enforced unless the user's enforcement mode is DISABLED.
Source
Thrown at languagetool-server/src/main/java/org/languagetool/server/RequestLimiter.java:179
private String getUserAgent(Map<String, List<String>> httpHeader) {
List<String> values = httpHeader.get("User-Agent");
if (values == null || values.isEmpty()) {
return null;
}
return values.get(0);
}
static void checkUserLimit(String referer, String userAgent, UserLimits user) {
Long maxRequests = user.getRequestsPerDay();
if (user.getPremiumUid() != null
&& maxRequests != null
&& user.getLimitEnforcementMode() != LimitEnforcementMode.DISABLED) {
if (user.getLimitEnforcementMode() == LimitEnforcementMode.PER_DAY) {
Long requestCount = DatabaseAccess.getInstance().getUserRequestCount(user.getPremiumUid());
//System.out.printf("requests for %d: %d / %d%n", user.getPremiumUid(), requestCount, maxRequests);
if (requestCount > maxRequests) {
String message = "limit: " + maxRequests + ", requests: " + requestCount + ", enforcement: " + user.getLimitEnforcementMode().name();
throw new TooManyRequestsException("User request limit of " + maxRequests + " per day exceeded. Try again after midnight UTC.");
}
}
}
}
void checkLimit(String ipAddress, Map<String, String> parameters, Map<String, List<String>> httpHeader) {
int requestsByIp = 0;
int requestSizeByIp = 0;
int requestsByFingerprint = 0;
int requestSizeByFingerprint = 0;
// all requests before this date are considered old:
Date thresholdDate = new Date(System.currentTimeMillis() - requestLimitPeriodInSeconds * 1000L);
String fingerprint = computeFingerprint(httpHeader, parameters);
String referer = getReferer(httpHeader);
String userAgent = getUserAgent(httpHeader);
Long clientId = getClientId(parameters);
String user = parameters.get("username");
boolean whitelistedUser = user != null && whitelistUsers.contains(user);View on GitHub (pinned to 2e990059ce)
Solutions
- Wait until after midnight UTC when the daily counter resets
- Upgrade the user's daily request quota in the server configuration/database
- Distribute traffic across multiple licensed users or add client-side throttling/backoff
Defensive patterns
Strategy: retry
Validate before calling
// track local daily usage per user and compare to known quota
if (usageCounter.today >= userQuotaPerDay) throw new Error('Daily quota would be exceeded; defer requests'); Try / catch
try {
return await check(text);
} catch (e) {
if (e.status === 429 && /per day exceeded/.test(e.message)) {
await waitUntilMidnightUTC();
return check(text);
}
throw e;
} Prevention
- Implement client-side daily quotas per API user
- Avoid sharing one premium credential across many services
- Schedule bulk jobs to spread usage across days
When it happens
Trigger: User with LimitEnforcementMode.PER_DAY and premiumUid whose getUserRequestCount exceeds maxRequests during checkUserLimit.
Common situations: CI pipelines or cron jobs burning through daily quotas, shared API credentials used by many services, quota reduced by an admin while usage stayed high, or a retry loop after failures.
Related errors
- Whitelist request limit of requests per seconds exceeded
- Client request limit of requests per seconds exceeded
- IP request limit of requests per seconds exceeded
- Client request size limit of bytes per seconds exceeded in
- IP request size limit of bytes per seconds exceeded in tex
AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06).
Data as JSON: /api/errors/19eb8c534f10c708.
Report an issue: GitHub.