{"record":{"id":"dc7e4483b789bf11","repo":"stanfordnlp/CoreNLP","slug":"oldtag-starts-with-b-entity-at-position-should-no","errorCode":null,"errorMessage":"oldTag starts with B, entity at position should not be null","messagePattern":"oldTag starts with B, entity at position should not be null","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/edu/stanford/nlp/ie/EntityCachingAbstractSequencePriorBIO.java","lineNumber":228,"sourceCode":"    return false;\n  }\n\n  @Override\n  public void updateSequenceElement(int[] sequence, int position, int oldVal) {\n    this.sequence = sequence;\n\n    if (sequence[position] == oldVal)\n      return;\n\n    if (VERBOSE) log.info(\"changing position \"+position+\" from \" +classIndex.get(oldVal)+\" to \"+classIndex.get(sequence[position]));\n\n    if (sequence[position] == backgroundSymbol) { // new tag is O\n      String oldRawTag = classIndex.get(oldVal);\n      String[] oldParts = oldRawTag.split(\"-\");\n      if (oldParts[0].equals(\"B\")) { // old tag was a B, current entity definitely affected, also check next one\n        EntityBIO entity = entities[position];\n        if (entity == null)\n          throw new RuntimeException(\"oldTag starts with B, entity at position should not be null\");\n        // remove entities for all words affected by this entity\n        for (int i=0; i < entity.words.size(); i++) {\n          entities[position+i] = null;\n        }\n      } else { // old tag was a I, check previous one\n        if (entities[position] != null) { // this was part of an entity, shortened\n          if (VERBOSE) log.info(\"splitting off prev entity\");\n          EntityBIO oldEntity = entities[position];\n          int oldLen = oldEntity.words.size();\n          int offset = position - oldEntity.startPosition;\n          List<String> newWords = new ArrayList<>();\n          for (int i=0; i<offset; i++) {\n            newWords.add(oldEntity.words.get(i));\n          }\n          oldEntity.words = newWords;\n          oldEntity.otherOccurrences = otherOccurrences(oldEntity);\n          // need to clean any remaining entity\n          for (int i=0 ; i < oldLen - offset; i++) {","sourceCodeStart":210,"sourceCodeEnd":246,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/ie/EntityCachingAbstractSequencePriorBIO.java#L210-L246","documentation":"EntityCachingAbstractSequencePriorBIO maintains a cache of BIO entities parallel to the tag sequence. updateSequenceElement validates internal consistency: if the changed tag was a 'B-' tag, an entity must exist at that position; if the cache is null, the cache is corrupt and it throws a RuntimeException.","triggerScenarios":"Calling scoresOf/sequence mutation paths where the entity cache was not built consistently with the tag sequence — e.g. a sequence containing B- tags whose entity cache was never populated, or mutated through an unexpected path.","commonSituations":"Custom DocumentReaderAndWriter or label schemes feeding B- labels without matching entity construction; modifying the label index or sequence outside the supported API; mismatched BIO vs IO label encodings.","solutions":["Ensure the label scheme is consistent BIO (every B- has a following I- or is a single-token entity) and that entities are built by the class's own setup","Verify the sequence passed to scoresOf comes from the same reader/label scheme used to build the cache","Report/inspect with a debugger: entities[position] null while classIndex.get(oldVal) starts with 'B' indicates external mutation","If you modified updateSequenceElement or the cache-building code, restore it or rebuild entities[position] before updating"],"exampleFix":"// before: sequence labels use B- but cache built assuming IO scheme\nprior.scoresOf(doc, sequence); // RuntimeException\n// after: use the matching BIO reader/labels so cache includes entities\nList<CoreLabel> doc = bioReader.processDocument(text); // builds consistent B-/I- tags\nprior.scoresOf(doc, sequence);","handlingStrategy":"validation","validationCode":"// ensure sequence uses the same BIO label scheme the prior was built with\nString firstTag = classIndex.get(sequence[0]);\nif (firstTag != null && firstTag.startsWith(\"B-\"))\n  throw new IllegalStateException(\"B- labels require entity cache built via BIO reader\");","typeGuard":null,"tryCatchPattern":"try {\n  scores = prior.scoresOf(doc, sequence);\n} catch (RuntimeException e) {\n  if (e.getMessage().contains(\"entity at position should not be null\"))\n    log.error(\"entity cache desync — rebuild sequence via the same label scheme\");\n  throw e;\n}","preventionTips":["Do not mutate label sequences outside the class's updateSequenceElement path","Use one consistent BIO/IO tagging scheme end-to-end","Don't hand-edit classIndex or entity arrays"],"tags":["java","corenlp","bio-tagging","invariant"],"backgroundTag":"internal-invariant-violation","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"}