stanfordnlp/CoreNLP · error · RuntimeException

Unexpected class label: score " + score + " became " +…

Error message

Unexpected class label: score " + score + " became " + classLabel

What it means

Class labels are computed by flooring score*5 and rounding to an integer that must be in [0,4]. A score outside the expected [0,1] range (or a malformed one) produces a label outside that range, so the converter throws RuntimeException.

Solutions

  1. Ensure sentiment scores are probabilities in [0,1]; fix or regenerate sentiment_labels.txt
  2. Verify the parser reads the score column, not an id column
  3. Clamp/validate scores in preprocessing: score = Math.max(0, Math.min(1, score))

Example fix

// before
score = Double.parseDouble(fields[2]); // wrong column
// after
score = Double.parseDouble(fields[1]);
Defensive patterns

Strategy: validation

Validate before calling

double score = sentimentScores.get(phraseId);
if (score < 0.0 || score > 1.0) throw new IllegalArgumentException("Score out of [0,1]: " + score);

Try / catch

try { label = Math.round((float) Math.floor(score * 5f)); } catch (RuntimeException e) { /* clamp: */ score = Math.max(0, Math.min(1, score)); }

Prevention

When it happens

Trigger: sentiment_labels.txt containing values >1 or <0 (e.g. raw counts instead of probabilities, or a mis-parsed column), leading floor(score*5) to yield -1 or 5+.

Common situations: Hand-edited label files, using the wrong column of sentiment_labels.txt, joining label data from a different corpus with a different score scale.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10). Data as JSON: /api/errors/6ff1c2d606e5c111. Report an issue: GitHub.

Appendix: source

Thrown at src/edu/stanford/nlp/sentiment/ReadSentimentDataset.java:282

      // If a particular phrase doesn't have -LRB- -RRB- we fall back
      // to the unescaped versions.
      Integer phraseId = phraseIds.get(CollectionUtils.transformAsList(words, TRANSFORM_PARENS));
      if (phraseId == null) {
        phraseId = phraseIds.get(words);
      }
      if (phraseId == null) {
        throw new RuntimeException("Could not find phrase id for phrase " + sentence);
      }
      // TODO: should we make this an option?  Perhaps we want cases
      // where the trees have the phrase id and not their class
      Double score = sentimentScores.get(phraseId);
      if (score == null) {
        throw new RuntimeException("Could not find sentiment score for phrase id " + phraseId);
      }

      int classLabel = Math.round((float) Math.floor(score * (float) 5));
      if (classLabel > 4 || classLabel < 0) {
        throw new RuntimeException("Unexpected class label: score " + score + " became " + classLabel);
      }
      subtrees[i].label().setValue(Integer.toString(classLabel));
    }

    for (int i = 0; i < sentence.size(); ++i) {
      Tree leaf = subtrees[i].children()[0];
      for (Pair<String, String> replacement : singleWordReplacements) {
        if (leaf.label().value().equals(replacement.first)) {
          leaf.label().setValue(replacement.second);
        }
      }
      leaf.label().setValue(escaper.escapeString(leaf.label().value()));
    }

    for (int i = 0; i < transformations.length; ++i) {
      root = Tsurgeon.processPattern(transformations[i].tregex,
                                     transformations[i].surgery, root);
    }

View on GitHub (pinned to 1b7edd19c4)