{"record":{"id":"67a5c5696ac742a3","repo":"stanfordnlp/CoreNLP","slug":"timex3-should-only-contain-text-child-67a5c5","errorCode":null,"errorMessage":"TIMEX3 should only contain text ${child}","messagePattern":"TIMEX3 should only contain text (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/edu/stanford/nlp/time/HeidelTimeAnnotator.java","lineNumber":218,"sourceCode":"        int charEnd = token.get(CoreAnnotations.CharacterOffsetEndAnnotation.class);\n        beginMap.put(charBegin,tokBegin);\n        endMap.put(charEnd,tokEnd);\n      }\n    }\n    List<CoreMap> timexMaps = new ArrayList<>();\n    int offset = 0;\n    NodeList docNodes = docElem.getChildNodes();\n    for (int i = 0; i < docNodes.getLength(); i++) {\n      Node content = docNodes.item(i);\n      if (content instanceof Text) {\n        Text text = (Text)content;\n        offset += text.getWholeText().length();\n      } else if (content instanceof Element) {\n        Element child = (Element)content;\n        if (child.getNodeName().equals(\"TIMEX3\")) {\n          Timex timex = new Timex(child);\n          if (child.getChildNodes().getLength() != 1) {\n            throw new RuntimeException(\"TIMEX3 should only contain text \" + child);\n          }\n          String timexText = child.getTextContent();\n          CoreMap timexMap = new ArrayCoreMap();\n          timexMap.set(TimeAnnotations.TimexAnnotation.class, timex);\n          timexMap.set(CoreAnnotations.TextAnnotation.class, timexText);\n          int charBegin = offset;\n          timexMap.set(CoreAnnotations.CharacterOffsetBeginAnnotation.class, offset);\n          offset += timexText.length();\n          timexMap.set(CoreAnnotations.CharacterOffsetEndAnnotation.class, offset);\n          int charEnd = offset;\n          //(tokens)\n          if(haveTokenOffsets){\n            Integer tokBegin = beginMap.get(charBegin);\n            int searchStep = 1;          //if no exact match, search around the character offset\n            while(tokBegin == null){\n              tokBegin = beginMap.get(charBegin - searchStep);\n              if(tokBegin == null){\n                tokBegin = beginMap.get(charBegin + searchStep);","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/time/HeidelTimeAnnotator.java#L200-L236","documentation":"HeidelTimeAnnotator's toTimexCoreMaps parses HeidelTime's XML output; each TIMEX3 element produced by HeidelTime is expected to wrap exactly one text node. When a TIMEX3 element has zero or more than one child nodes (e.g. nested elements or split text), the annotator throws this RuntimeException because the offset/token mapping logic cannot handle that shape.","triggerScenarios":"Running the HeidelTimeAnnotator (or a StanfordCoreNLP pipeline containing 'heideltime') on a document whose HeidelTime output contains a TIMEX3 element with nested/multiple children — typically when HeidelTime tags a span that includes markup or the external heideltime.jar version emits non-flat TIMEX3 elements.","commonSituations":"Using a mismatched or customized heideltime.jar whose output format differs from what this annotator expects; documents with unusual date expressions causing HeidelTime to emit nested TIMEX3 tags; passing pre-annotated XML rather than plain text.","solutions":["Verify the external heideltime.jar version matches what this CoreNLP version expects; replace with the bundled/supported version","Inspect the HeidelTime XML output (enable debug printing) to find the offending TIMEX3 element and check why it has multiple children","Pre-normalize the input text so HeidelTime does not emit nested tags (e.g. strip XML/HTML from the document before annotation)","Patch toTimexCoreMaps to flatten multi-child TIMEX3 elements by iterating child text nodes instead of requiring exactly one"],"exampleFix":"// before: hard failure on non-flat TIMEX3\nif (child.getChildNodes().getLength() != 1) {\n  throw new RuntimeException(\"TIMEX3 should only contain text \" + child);\n}\n// after: flatten multiple text children\nStringBuilder sb = new StringBuilder();\nNodeList kids = child.getChildNodes();\nfor (int j = 0; j < kids.getLength(); j++) {\n  if (kids.item(j) instanceof Text) sb.append(kids.item(j).getTextContent());\n}\nString timexText = sb.toString();","handlingStrategy":"try-catch","validationCode":"// Ensure input to HeidelTimeAnnotator is plain, tokenizable text\nString docText = annotation.get(CoreAnnotations.TextAnnotation.class);\nif (docText == null || docText.trim().isEmpty()) {\n    throw new IllegalArgumentException(\"document text is empty\");\n}\nif (docText.contains(\"<TIMEX3\")) {\n    throw new IllegalArgumentException(\"input already contains TIMEX3 markup; pass plain text\");\n}","typeGuard":"static boolean isFlatTimex3(Element el) {\n    return \"TIMEX3\".equals(el.getNodeName()) && el.getChildNodes().getLength() == 1\n        && el.getChildNodes().item(0) instanceof Text;\n}","tryCatchPattern":"try {\n    pipeline.annotate(annotation);\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"TIMEX3 should only contain text\")) {\n        // fall back: skip time annotation or re-run with sanitized input\n        logger.warn(\"HeidelTime produced non-flat TIMEX3; skipping doc \" + annotation.get(CoreAnnotations.DocIDAnnotation.class));\n    } else {\n        throw e;\n    }\n}","preventionTips":["Use the heideltime.jar version bundled/tested with your CoreNLP release","Strip XML/HTML markup from documents before running HeidelTime","Test new corpora for odd date expressions that produce nested TIMEX3 output","Wrap annotator calls so one bad document does not kill the whole pipeline"],"tags":["java","nlp","xml-parsing","runtime-exception"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a","analyzedAt":"2026-09-10T02:24:07.274Z","contentChangedAt":"2026-09-10T02:24:07.274Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}