{"record":{"id":"3ce3e8a649f4fd3d","repo":"stanfordnlp/CoreNLP","slug":"label-dictionary-is-already-locked-3ce3e8","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":94,"sourceCode":"  /**\n   * Get the allowed label set for an observation.\n   *\n   * @param observation\n   * @return The allowed label set, or null if the observation is unconstrained.\n   */\n  public int[] getConstrainedSet(String observation) {\n    int i = observationIndex.indexOf(observation);\n    return i >= 0 ? labelDictionary[i] : null;\n  }\n\n  /**\n   * Setup the constrained label sets and free bookkeeping resources.\n   *\n   * @param threshold\n   * @param labelIndex\n   */\n  public void lock(int threshold, Index<String> labelIndex) {\n    if (labelDictionary != null) throw new RuntimeException(\"Label dictionary is already locked\");\n    log.info(\"Label dictionary enabled\");\n    System.err.printf(\"#observations: %d%n\", (int) observationCounts.totalCount());\n    Counters.retainAbove(observationCounts, threshold);\n    Set<String> constrainedObservations = observationCounts.keySet();\n    labelDictionary = new int[constrainedObservations.size()][];\n    observationIndex = new HashIndex<>(constrainedObservations.size());\n    for (String observation : constrainedObservations) {\n      int i = observationIndex.addToIndex(observation);\n      assert i < labelDictionary.length;\n      Set<String> allowedLabels = observedLabels.get(observation);\n      labelDictionary[i] = new int[allowedLabels.size()];\n      int j = 0;\n      for (String label : allowedLabels) {\n        labelDictionary[i][j++] = labelIndex.indexOf(label);\n      }\n      if (DEBUG) {\n        System.err.printf(\"%s : %s%n\", observation, allowedLabels.toString());\n      }","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/ie/crf/LabelDictionary.java#L76-L112","documentation":"lock() finalizes the LabelDictionary: it retains frequent observations, builds the int[][] label dictionary and observation index, and frees the counters. It must run exactly once; a second call finds labelDictionary != null and throws to prevent destroying the already-computed constrained label sets.","triggerScenarios":"Calling lock(threshold, labelIndex) twice on the same LabelDictionary — e.g. a setup routine that may run multiple times (re-loading a model, re-running feature initialization) and invokes lock each time.","commonSituations":"Idempotency bugs: initialization code invoked on both first load and model reload; multiple CRF classifiers sharing one dictionary but each calling lock during their own setup.","solutions":["Guard the call: only lock if !isLocked() (check the internal state or expose/track a boolean).","Move lock() into a one-time initialization path that is provably executed once per dictionary.","Use a fresh LabelDictionary if a new lock with different threshold/labelIndex is genuinely needed."],"exampleFix":"// before\nlabelDict.lock(threshold, labelIndex); // second call throws\nlabelDict.lock(threshold, labelIndex);\n\n// after\nif (!labelDict.isLocked()) {\n  labelDict.lock(threshold, labelIndex);\n}","handlingStrategy":"validation","validationCode":"// Java: make lock idempotent at the call site\nif (!lockedDictionaries.contains(dict)) {\n  dict.lock(threshold, labelIndex);\n  lockedDictionaries.add(dict);\n}","typeGuard":null,"tryCatchPattern":"// Java\ntry {\n  dict.lock(threshold, labelIndex);\n} catch (RuntimeException e) {\n  if (!e.getMessage().contains(\"already locked\")) throw e;\n  // safe to ignore: dictionary already finalized\n}","preventionTips":["Invoke lock() exactly once, ideally in a dedicated one-time init method.","Make setup code idempotent so model reloads don't re-run lock().","Track locked dictionaries in a Set if multiple classifiers share them."],"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"}