{"record":{"id":"7fb519ca4ca6c2be","repo":"languagetool-org/languagetool","slug":"only-text-and-markup-are-supported-in-annotat","errorCode":null,"errorMessage":"Only 'text' and 'markup' are supported in 'annotation' list: ","messagePattern":"Only 'text' and 'markup' are supported in 'annotation' list: ","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"languagetool-server/src/main/java/org/languagetool/server/ApiV2.java","lineNumber":496,"sourceCode":"    //   {text: 'more text'},\n    //   {markup: '</b>'}\n    // ]\n    //\n    for (JsonNode node : data.get(\"annotation\")) {\n      if (node.get(\"text\") != null && node.get(\"markup\") != null) {\n        throw new BadRequestException(\"Only either 'text' or 'markup' are supported in an object in 'annotation' list, not both: \" + node);\n      } else if (node.get(\"text\") != null && node.get(\"interpretAs\") != null) {\n        throw new BadRequestException(\"'text' cannot be used with 'interpretAs' (only 'markup' can): \" + node);\n      } else if (node.get(\"text\") != null) {\n        atb.addText(node.get(\"text\").asText());\n      } else if (node.get(\"markup\") != null) {\n        if (node.get(\"interpretAs\") != null) {\n          atb.addMarkup(node.get(\"markup\").asText(), node.get(\"interpretAs\").asText());\n        } else {\n          atb.addMarkup(node.get(\"markup\").asText());\n        }\n      } else {\n        throw new BadRequestException(\"Only 'text' and 'markup' are supported in 'annotation' list: \" + node);\n      }\n    }\n    return atb.build();\n  }\n\n  String getLanguages() throws IOException {\n    StringWriter sw = new StringWriter();\n    try (JsonGenerator g = factory.createGenerator(sw)) {\n      g.writeStartArray();\n      List<Language> languages = new ArrayList<>(Languages.get());\n      Set<String> longCodes = new HashSet<>();\n      for (Language lang : languages) {\n        g.writeStartObject();\n        g.writeStringField(\"name\", lang.getName());\n        g.writeStringField(\"code\", lang.getShortCode());\n        g.writeStringField(\"longCode\", lang.getShortCodeWithCountryAndVariant());\n        longCodes.add(lang.getShortCodeWithCountryAndVariant());\n        g.writeEndObject();","sourceCodeStart":478,"sourceCodeEnd":514,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-server/src/main/java/org/languagetool/server/ApiV2.java#L478-L514","documentation":"Each object in the 'annotation' list must have a non-null 'text' or 'markup' key. If a node has neither (e.g. only 'interpretAs' or an unrelated/empty object), LanguageTool throws BadRequestException since it cannot interpret the entry.","triggerScenarios":"POSTing data with annotation objects like {} or {\"interpretAs\":\"foo\"} or {\"other\":\"x\"} to /v2/check.","commonSituations":"Serialization bugs that drop the 'text'/'markup' key when its value is empty; schema drift between client and API versions.","solutions":["Ensure every annotation object has exactly one of 'text' or 'markup'.","Remove empty or malformed objects from the list.","Inspect the offending node echoed in the message to find the malformed entry."],"exampleFix":"// before\n{\"annotation\":[{\"interpretAs\":\"x\"}]}\n// after\n{\"annotation\":[{\"text\":\"x\"}]}","handlingStrategy":"validation","validationCode":"annotation.forEach((n, i) => {\n  if (n.text == null && n.markup == null) throw new Error(`annotation[${i}] needs 'text' or 'markup'`);\n});","typeGuard":"function isValidAnnotationNode(n) {\n  return n != null && (n.text != null || n.markup != null);\n}","tryCatchPattern":"try {\n  const res = await fetch('/v2/check', { method: 'POST', body: form });\n  if (res.status === 400) throw new Error(await res.text());\n} catch (e) {\n  console.error('invalid annotation entry:', e.message);\n}","preventionTips":["Filter out empty objects before sending annotation lists.","Ensure serializers do not omit empty-string text/markup keys (use '' not omission).","Type annotation entries in your client code."],"tags":["http","api","json","validation","languagetool"],"backgroundTag":"schema-validation-failed","analyzedSha":"2e990059ce67d5e2a0f7f7ca5d31160c6709df4b","analyzedAt":"2026-09-06T09:20:17.015Z","contentChangedAt":"2026-09-06T09:20:17.015Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}