{"record":{"id":"73b904ae4556155c","repo":"stanfordnlp/CoreNLP","slug":"label-dictionary-is-already-locked","errorCode":null,"errorMessage":"Label dictionary is already locked.","messagePattern":"Label dictionary is already locked\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/edu/stanford/nlp/ie/crf/LabelDictionary.java","lineNumber":60,"sourceCode":"  private int[][] labelDictionary;\n\n  /**\n   * Constructor.\n   */\n  public LabelDictionary() {\n    this.observationCounts = new ClassicCounter<>(DEFAULT_CAPACITY);\n    this.observedLabels = Generics.newHashMap(DEFAULT_CAPACITY);\n  }\n\n  /**\n   * Increment counts for an observation/label pair.\n   *\n   * @param observation\n   * @param label\n   */\n  public void increment(String observation, String label) {\n    if (labelDictionary != null) {\n      throw new RuntimeException(\"Label dictionary is already locked.\");\n    }\n    observationCounts.incrementCount(observation);\n    if ( ! observedLabels.containsKey(observation)) {\n      observedLabels.put(observation, new HashSet<>());\n    }\n    observedLabels.get(observation).add(label.intern());\n  }\n\n  /**\n   * True if this observation is constrained, and false otherwise.\n   */\n  public boolean isConstrained(String observation) {\n    return observationIndex.indexOf(observation) >= 0;\n  }\n\n  /**\n   * Get the allowed label set for an observation.\n   *","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/ie/crf/LabelDictionary.java#L42-L78","documentation":"LabelDictionary supports a two-phase lifecycle: collect observation counts via increment(), then freeze them via lock(). Once lock() has run, labelDictionary is non-null and no further observations may be recorded, because the constrained label sets are already materialized. Calling increment after that point throws this RuntimeException.","triggerScenarios":"Calling increment(observation, label) after lock(threshold, labelIndex) has already been called on the same LabelDictionary instance — e.g. training a second dataset with a dictionary that was locked for the first, or calling increment inside an loop that runs after lock.","commonSituations":"Reusing a LabelDictionary across multiple training runs; pipeline code that calls lock() for CRF feature setup and then continues accumulating observations; adding new training data to an already-locked dictionary.","solutions":["Create a new LabelDictionary for each collection phase; call lock() only after all increment() calls are done.","Restructure the pipeline so lock() is the last step before CRF training begins.","If you need to add data after locking, rebuild the dictionary: new LabelDictionary, re-increment everything, lock again."],"exampleFix":"// before\ndict.increment(\"foo\", \"LOC\"); // after lock() already ran -> throws\n\n// after\nLabelDictionary dict2 = new LabelDictionary(); // fresh instance for new data\ndict2.increment(\"foo\", \"LOC\");\ndict2.lock(threshold, labelIndex);","handlingStrategy":"try-catch","validationCode":"// Java: guard before incrementing\nboolean locked;\ntry {\n  java.lang.reflect.Field f = LabelDictionary.class.getDeclaredField(\"labelDictionary\");\n  f.setAccessible(true);\n  locked = f.get(dict) != null;\n} catch (Exception e) { locked = false; }\nif (!locked) dict.increment(observation, label);","typeGuard":null,"tryCatchPattern":"// Java\ntry {\n  dict.increment(observation, label);\n} catch (RuntimeException e) {\n  if (e.getMessage().contains(\"already locked\")) {\n    dict = new LabelDictionary(); // restart collection phase\n    dict.increment(observation, label);\n  } else throw e;\n}","preventionTips":["Treat LabelDictionary as single-use: increment phase, then lock, then discard.","Call lock() only after the entire dataset has been scanned.","Never share one dictionary across sequential training runs."],"tags":["java","nlp","crf","lifecycle"],"backgroundTag":"invalid-state-transition","analyzedSha":"1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a","analyzedAt":"2026-09-10T02:24:07.274Z","contentChangedAt":"2026-09-10T02:24:07.274Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}