stanfordnlp/CoreNLP · error · RuntimeException

flags.softmaxOutputLayer == true, but neither…

Error message

flags.softmaxOutputLayer == true, but neither flags.sparseOutputLayer or flags.tieOutputLayer is true

What it means

CRFNonLinearSecondOrderLogConditionalObjectiveFunction's constructor requires that a softmax output layer be used together with either a sparse output layer or tied output layer. When flags.softmaxOutputLayer is true but both sparseOutputLayer and tieOutputLayer are false, the required layout is undefined, so construction fails fast with a RuntimeException.

Solutions

  1. Set flags.sparseOutputLayer = true alongside softmaxOutputLayer.
  2. Alternatively set flags.tieOutputLayer = true if parameter tying is the intended layout.
  3. Or disable softmaxOutputLayer if the plain output layer is sufficient.
  4. Review the SeqClassifierFlags combinations documented for useNonLinearCRF training.

Example fix

// before
flags.useNonLinearCRF = true;
flags.softmaxOutputLayer = true;
// after
flags.useNonLinearCRF = true;
flags.softmaxOutputLayer = true;
flags.sparseOutputLayer = true; // or flags.tieOutputLayer = true;
Defensive patterns

Strategy: validation

Validate before calling

// validate flag combinations before training
if (props.getProperty("softmaxOutputLayer", "false").equals("true") &&
    !props.getProperty("sparseOutputLayer", "false").equals("true") &&
    !props.getProperty("tieOutputLayer", "false").equals("true")) {
  throw new IllegalArgumentException("softmaxOutputLayer requires sparseOutputLayer or tieOutputLayer");
}

Try / catch

try {
  classifier.train(props);
} catch (RuntimeException e) {
  if (e.getMessage().contains("softmaxOutputLayer == true")) {
    props.setProperty("sparseOutputLayer", "true");
    classifier.train(props);
  } else throw e;
}

Prevention

When it happens

Trigger: Building the objective function with SeqClassifierFlags where softmaxOutputLayer=true, sparseOutputLayer=false, tieOutputLayer=false -- i.e. useOutputLayer is active (non-linear CRF training) but the softmax flag's structural prerequisite is missing.

Common situations: Enabling softmaxOutputLayer in training properties while forgetting to also set sparseOutputLayer or tieOutputLayer; copying flag sets from examples that used the linear CRF instead of the non-linear one.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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

Appendix: source

Thrown at src/edu/stanford/nlp/ie/crf/CRFNonLinearSecondOrderLogConditionalObjectiveFunction.java:121

    this.backgroundSymbol = flags.backgroundSymbol;
    this.sigma = flags.sigma;
    this.outputLayerSize = numClasses;
    this.outputLayerSize4Edge = numClasses * numClasses;
    this.numHiddenUnits = flags.numHiddenUnits;
    this.inputLayerSize = numHiddenUnits * numClasses;
    this.inputLayerSize4Edge = numHiddenUnits * numClasses * numClasses;
    this.numNodeFeatures = numNodeFeatures;
    this.numEdgeFeatures = numEdgeFeatures;
    this.useOutputLayer = flags.useOutputLayer;
    this.useHiddenLayer = flags.useHiddenLayer;
    this.useSigmoid = flags.useSigmoid;
    this.docWindowLabels = new int[data.length][];
    if (!useOutputLayer) {
      log.info("Output layer not activated, inputLayerSize must be equal to numClasses, setting it to " + numClasses);
      this.inputLayerSize = numClasses;
      this.inputLayerSize4Edge = numClasses * numClasses;
    } else if (flags.softmaxOutputLayer && !(flags.sparseOutputLayer || flags.tieOutputLayer)) {
      throw new RuntimeException("flags.softmaxOutputLayer == true, but neither flags.sparseOutputLayer or flags.tieOutputLayer is true");
    }
    // empiricalCounts();
  }

  @Override
  public int domainDimension() {
    if (domainDimension < 0) {
      originalFeatureCount = 0;
      for (int aMap : map) {
        int s = labelIndices.get(aMap).size();
        originalFeatureCount += s;
      }
      domainDimension = 0;
      domainDimension += inputLayerSize4Edge * numEdgeFeatures;
      domainDimension += inputLayerSize * numNodeFeatures;
      beforeOutputWeights = domainDimension;
      if (useOutputLayer) {
        if (flags.sparseOutputLayer) {

View on GitHub (pinned to 1b7edd19c4)