stanfordnlp/CoreNLP · critical · RuntimeException

Could not open temporary feature index file for reading.

Error message

Could not open temporary feature index file for reading.

What it means

On subsequent training iterations with flags.saveFeatureIndexToDisk, CRFClassifier reloads the feature index written earlier from the temp file via IOUtils.readObjectFromFile. If reading or deserializing fails (file deleted, truncated, or class mismatch), the Exception is wrapped in this RuntimeException since the iteration cannot continue without the index.

Solutions

  1. Point java.io.tmpdir to a stable private directory (-Djava.io.tmpdir=/your/dir) that auto-cleaners don't touch.
  2. Disable saveFeatureIndexToDisk to keep the index in memory and restart training.
  3. Fix the root cause shown in the wrapped exception (permissions, corrupt file, serialization classpath).

Example fix

// before
java -Djava.io.tmpdir=/tmp -cp ... edu.stanford.nlp.ie.crf.CRFClassifier ...
// after (on a machine where /tmp is auto-cleaned)
java -Djava.io.tmpdir=/data/crf-tmp -cp ... edu.stanford.nlp.ie.crf.CRFClassifier ...
Defensive patterns

Strategy: try-catch

Validate before calling

File tmpDir = new File(System.getProperty("java.io.tmpdir"));
if (!tmpDir.canRead()) {
  throw new IllegalStateException("tmpdir unreadable; temp feature index files may disappear between iterations");
}

Try / catch

try {
  classifier.train(files);
} catch (RuntimeException e) {
  if (String.valueOf(e.getMessage()).contains("temporary feature index file for reading")) {
    // temp file vanished or is corrupt: restart with in-memory index
    props.remove("saveFeatureIndexToDisk");
  } else throw e;
}

Prevention

When it happens

Trigger: flags.saveFeatureIndexToDisk=true and the featIndexN.tmp file is missing, unreadable, or corrupt when the next training iteration starts — e.g. a tmp cleaner wiped it, a concurrent job overwrote it, or the earlier write silently failed.

Common situations: Long training on shared machines where /tmp is periodically cleaned; multi-node jobs without shared storage; disk pressure truncating the file; deserialization classpath mismatches.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

Thrown at src/edu/stanford/nlp/ie/crf/CRFClassifier.java:1703

      if (oneDimWeights != null) {
        this.weights = to2D(oneDimWeights, labelIndices, map);
      }

      // if (flags.useFloat) {
      //   oneDimWeights = trainWeightsUsingFloatCRF(data, labels, evaluators, i, featureVals);
      // } else if (flags.numLopExpert > 1) {
      //   oneDimWeights = trainWeightsUsingLopCRF(data, labels, evaluators, i, featureVals);
      // } else {
      //   oneDimWeights = trainWeightsUsingDoubleCRF(data, labels, evaluators, i, featureVals);
      // }

      // save feature index to disk and read in later
      if (flags.saveFeatureIndexToDisk) {
        try {
          log.info("Reading temporary feature index file.");
          featureIndex = IOUtils.readObjectFromFile(featIndexFile);
        } catch (Exception e) {
          throw new RuntimeException("Could not open temporary feature index file for reading.");
        }
      }

      if (i != flags.numTimesPruneFeatures) {
        dropFeaturesBelowThreshold(flags.featureDiffThresh);
        log.info("Removing features with weight below " + flags.featureDiffThresh + " and retraining...");
      }
    }
  }

  public static float[][] to2D(double[] weights, List<Index<CRFLabel>> labelIndices, int[] map) {
    float[][] newWeights = new float[map.length][];
    int index = 0;
    for (int i = 0; i < map.length; i++) {
      newWeights[i] = new float[labelIndices.get(map[i]).size()];
      final int arrLength = labelIndices.get(map[i]).size();
      for (int j = 0; j < arrLength; j++) {
        newWeights[i][j] = (float) weights[index++];

View on GitHub (pinned to 1b7edd19c4)