languagetool-org/languagetool · error · BadRequestException
'data' key in JSON requires 'text' or 'annotation' key
Error message
'data' key in JSON requires 'text' or 'annotation' key
What it means
If the 'data' JSON payload of /v2/check contains neither a 'text' nor an 'annotation' key, there is nothing to check, so the server throws BadRequestException (HTTP 400) with this message. Note this also fires when a key exists but maps to JSON null, since data.get("text") returns null for null values.
Source
Thrown at languagetool-server/src/main/java/org/languagetool/server/ApiV2.java:166
throw new BadRequestException("Set only 'text' or 'data' parameter, not both");
} else if (parameters.containsKey("text")) {
aText = new AnnotatedTextBuilder().addText(parameters.get("text")).build();
} else if (parameters.containsKey("data")) {
ObjectMapper mapper = new ObjectMapper();
JsonNode data;
try {
data = mapper.readTree(parameters.get("data"));
} catch (JsonProcessingException e) {
throw new BadRequestException("Could not parse JSON from 'data' parameter", e);
}
if (data.get("text") != null && data.get("annotation") != null) {
throw new BadRequestException("'data' key in JSON requires either 'text' or 'annotation' key, not both");
} else if (data.get("text") != null) {
aText = getAnnotatedTextFromString(data, data.get("text").asText());
} else if (data.get("annotation") != null) {
aText = getAnnotatedTextFromJson(data);
} else {
throw new BadRequestException("'data' key in JSON requires 'text' or 'annotation' key");
}
} else {
throw new BadRequestException("Missing 'text' or 'data' parameter");
}
//get from config
if (config.logIp && aText.getPlainText().trim().equals(config.logIpMatchingPattern)) {
handleIpLogMatch(httpExchange, remoteAddress, parameters);
//no need to check text again rules
return;
}
textChecker.checkText(aText, httpExchange, parameters, errorRequestLimiter, remoteAddress);
}
private void handleIpLogMatch(HttpExchange httpExchange, String remoteAddress, Map<String, String> parameters) {
Logger logger = LoggerFactory.getLogger(ApiV2.class);
InetSocketAddress localAddress = httpExchange.getLocalAddress();
logger.info(String.format("Found log-my-IP text in request from: %s to: %s, requestParams: %s", remoteAddress, localAddress.toString(), parameters));
}View on GitHub (pinned to 2e990059ce)
Solutions
- Add a 'text' or 'annotation' key with the content to check
- Ensure the client serializes empty strings rather than dropping/nulling the text field
- Validate the payload shape client-side before the request
Example fix
// before
{"username":"alice"}
// after
{"username":"alice","annotation":[{"text":"Hello world"}]} Defensive patterns
Strategy: validation
Validate before calling
const d = JSON.parse(dataPayload);
if (d.text == null && d.annotation == null) {
throw new Error("data JSON needs a 'text' or 'annotation' key");
} Try / catch
try {
const res = await check({ data: JSON.stringify(d) });
} catch (e) {
if (/requires 'text' or 'annotation' key/.test(e.message)) {
console.error('data payload has no content to check');
} else throw e;
} Prevention
- Validate data payload shape client-side before sending
- Ensure serializers emit text/annotation even when empty rather than omitting them
- Keep meta fields separate from the required content key
When it happens
Trigger: POST /v2/check with data={} or data={"software":"..."} (metadata-only JSON), or data={"text":null}.
Common situations: Clients sending only meta fields (e.g. username/dictionary hints) without the actual content; serialization dropping empty text fields.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- 'data' key in JSON requires either 'text' or 'annotation' ke
- 'language' parameter missing
- Set only 'text' or 'data' parameter, not both
- Could not parse JSON from 'data' parameter
- Only either 'text' or 'markup' are supported in an object in
AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06).
Data as JSON: /api/errors/161277ff18db9b7e.
Report an issue: GitHub.