languagetool-org/languagetool · error · TextTooLongException
Your text exceeds the limit of {maxTextLength} characters (i
Error message
Your text exceeds the limit of {maxTextLength} characters (it's {length} characters). Please submit a shorter text. What it means
LanguageTool server enforces a per-request maximum text length (limits.getMaxTextLength(), default smaller for anonymous users). When the submitted plain-text length exceeds that limit it logs a MAX_TEXT_SIZE metric and throws TextTooLongException (HTTP 413-style) telling the client to submit a shorter text.
Source
Thrown at languagetool-server/src/main/java/org/languagetool/server/TextChecker.java:414
if (databaseLogger.isLogging()) {
DatabaseAccess db = DatabaseAccess.getInstance();
agentId = db.getOrCreateClientId(params.get("useragent"));
userId = limits.getPremiumUid();
}
String referrer = httpExchange.getRequestHeaders().getFirst("Referer");
String userAgent = httpExchange.getRequestHeaders().getFirst("User-Agent");
if (!config.isAnonymousAccessAllowed() && limits.getPremiumUid() == null) {
throw new AuthException("Anonymous access is prohibited on this server, please provide authentication.");
}
int length = aText.getPlainText().length();
if ("true".equals(params.get("languageChanged"))) {
log.info("languageChanged to " + params.get("language") + " for text with length " + aText.getPlainText().trim().length());
}
if (length > limits.getMaxTextLength()) {
ServerMetricsCollector.getInstance().logRequestError(ServerMetricsCollector.RequestErrorType.MAX_TEXT_SIZE);
throw new TextTooLongException("Your text exceeds the limit of " + limits.getMaxTextLength() +
" characters (it's " + length + " characters). Please submit a shorter text.");
}
// static because we can't rely on errorRequestLimiter, null when timeoutRequestLimit option not set
if (!config.isLocalApiMode()) {
try {
RequestLimiter.checkUserLimit(referrer, userAgent, limits);
} catch (TooManyRequestsException e) {
String response = "Error: Access denied: " + e.getMessage();
httpExchange.sendResponseHeaders(HttpURLConnection.HTTP_FORBIDDEN, response.getBytes(ENCODING).length);
httpExchange.getResponseBody().write(response.getBytes(ENCODING));
String message = "Blocked request from uid:" + userId + " because user limit is reached: ";
message += "limit = " + limits.getRequestsPerDay() + ", mode = " + limits.getLimitEnforcementMode() + ". ";
message += "Access from " + remoteAddress + ", ";
message += "HTTP user agent: " + userAgent + ", ";
message += "User agent param: " + params.get("useragent") + ", ";
message += "Referrer: " + referrer + ", ";
message += "language: " + params.get("language") + ", ";
message += "h: " + reqCounter.getHandleCount() + ", ";View on GitHub (pinned to 2e990059ce)
Solutions
- Split the text into chunks below the limit and check each chunk separately, merging results
- Authenticate with a premium account whose configured maxTextLength is higher
- Raise the server's maxTextLength configuration option if you operate the server
- Strip unnecessary content (markup, quotes) before submission to reduce length
Example fix
// before curl -d "text=$(cat bigdoc.txt)" -d language=en-US http://server/v2/check // after split -b 19000 bigdoc.txt part_; for f in part_*; do curl -d "text=$(cat $f)" -d language=en-US http://server/v2/check; done
Defensive patterns
Strategy: validation
Validate before calling
const MAX_LEN = 20000; // anonymous default; use your account's limit
if (text.length > MAX_LEN) {
return chunkText(text, MAX_LEN).map(checkChunk);
} Try / catch
try {
return await check(text);
} catch (e) {
if (e.status === 413 || /exceeds the limit/.test(e.message)) {
return chunkAndCheck(text, parseLimitFromMessage(e.message));
}
throw e;
} Prevention
- Check text.length before each request and chunk proactively
- Keep chunks well under the limit (e.g. 19KB) to account for overhead
- Authenticate to get the larger limit when checking long documents
- Remember the limit counts plain-text characters, not bytes or markup
When it happens
Trigger: POSTing a text (or data-annotated text) to /v2/check whose getPlainText().length() exceeds the configured limit — e.g. default 20KB anonymous limit or a custom maxTextLength server option — from checkText or its test callers.
Common situations: Pasting whole documents or books into the API, uploading large files, or anonymous clients hitting the smaller anonymous limit while assuming the authenticated (premium) limit applies.
Understand the failure class
Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.
Related errors
- 'language' parameter missing
- Set only 'text' or 'data' parameter, not both
- Could not parse JSON from 'data' parameter
- 'data' key in JSON requires either 'text' or 'annotation' ke
- 'data' key in JSON requires 'text' or 'annotation' key
AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06).
Data as JSON: /api/errors/60190dab0e5e5694.
Report an issue: GitHub.