stanfordnlp/CoreNLP · error · RuntimeException
Label dictionary is already locked
Error message
Label dictionary is already locked
What it means
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.
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.
Example fix
// before
labelDict.lock(threshold, labelIndex); // second call throws
labelDict.lock(threshold, labelIndex);
// after
if (!labelDict.isLocked()) {
labelDict.lock(threshold, labelIndex);
} Defensive patterns
Strategy: validation
Validate before calling
// Java: make lock idempotent at the call site
if (!lockedDictionaries.contains(dict)) {
dict.lock(threshold, labelIndex);
lockedDictionaries.add(dict);
} Try / catch
// Java
try {
dict.lock(threshold, labelIndex);
} catch (RuntimeException e) {
if (!e.getMessage().contains("already locked")) throw e;
// safe to ignore: dictionary already finalized
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Label dictionary is already locked.
- after W derivative, index() != x.length()
- conditionalLogProbGivenFirst requires of one less than…
- conditionalLogProbGivenNext requires given one less than…
- conditionalLogProbGivenPrevious requires given one less…
AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10).
Data as JSON: /api/errors/3ce3e8a649f4fd3d.
Report an issue: GitHub.
Appendix: source
Thrown at src/edu/stanford/nlp/ie/crf/LabelDictionary.java:94
/**
* Get the allowed label set for an observation.
*
* @param observation
* @return The allowed label set, or null if the observation is unconstrained.
*/
public int[] getConstrainedSet(String observation) {
int i = observationIndex.indexOf(observation);
return i >= 0 ? labelDictionary[i] : null;
}
/**
* Setup the constrained label sets and free bookkeeping resources.
*
* @param threshold
* @param labelIndex
*/
public void lock(int threshold, Index<String> labelIndex) {
if (labelDictionary != null) throw new RuntimeException("Label dictionary is already locked");
log.info("Label dictionary enabled");
System.err.printf("#observations: %d%n", (int) observationCounts.totalCount());
Counters.retainAbove(observationCounts, threshold);
Set<String> constrainedObservations = observationCounts.keySet();
labelDictionary = new int[constrainedObservations.size()][];
observationIndex = new HashIndex<>(constrainedObservations.size());
for (String observation : constrainedObservations) {
int i = observationIndex.addToIndex(observation);
assert i < labelDictionary.length;
Set<String> allowedLabels = observedLabels.get(observation);
labelDictionary[i] = new int[allowedLabels.size()];
int j = 0;
for (String label : allowedLabels) {
labelDictionary[i][j++] = labelIndex.indexOf(label);
}
if (DEBUG) {
System.err.printf("%s : %s%n", observation, allowedLabels.toString());
}View on GitHub (pinned to 1b7edd19c4)