stanfordnlp/CoreNLP · error · RuntimeException

format error unexpected featureFactory line:

Error message

format error unexpected featureFactory line: 

What it means

Thrown when the featureFactory line of the text-serialized model does not match the expected '<featureFactory> name </featureFactory>' layout: it must contain at least the open/close markers and the class name between them. The message appends the offending line.

Solutions

  1. Ensure the line is exactly '<featureFactory> edu.stanford.nlp...FeatureFactory </featureFactory>' on one line
  2. Reformat the line back to a single line if an editor wrapped it
  3. Regenerate the model with CRFClassifier.writeModel from the same CoreNLP version
  4. Confirm the FeatureFactory class name is fully qualified (the loader also calls Class.forName on it)

Example fix

// before: line wrapped/reformatted in the model file
// <featureFactory>
// edu.stanford.nlp.wordseg.ChineseSegmenterFeatureFactory
// </featureFactory>
// after: single line with markers
// <featureFactory> edu.stanford.nlp.wordseg.ChineseSegmenterFeatureFactory </featureFactory>
Defensive patterns

Strategy: validation

Validate before calling

// Validate the featureFactory line format before loading
static boolean featureFactoryLineValid(String line) {
  if (line == null) return false;
  String[] toks = line.split(" ");
  return toks.length >= 2 && toks[0].equals("<featureFactory>") && toks[toks.length - 1].equals("</featureFactory>");
}

Type guard

static boolean isFeatureFactoryLine(String line) {
  String[] toks = line == null ? new String[0] : line.split(" ");
  return toks.length >= 2 && "<featureFactory>".equals(toks[0]) && "</featureFactory>".equals(toks[toks.length - 1]);
}

Try / catch

try {
  CRFClassifier<CoreLabel> model = CRFClassifier.getClassifier(modelPath);
} catch (RuntimeException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("format error unexpected featureFactory line:")) {
    throw new IllegalStateException("featureFactory line malformed (check it is one unwrapped line with both markers).", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: CRFClassifier.getClassifier on a model whose featureFactory line lacks '<featureFactory>'/'</featureFactory>' markers, has fewer than 2 space-separated tokens, or was wrapped/reformatted onto multiple lines.

Common situations: Text editors or formatters reflowed the long featureFactory line; custom models whose writer used a different marker format; edits or corruption in the flags/featureFactory region.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

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

      count = 0;
      while (count < embeddingSize) {
        line = br.readLine().trim();
        toks = line.split("\\t");
        String word = toks[0];
        double[] arr = ArrayUtils.toDoubleArray(toks[1].split(" "));
        embeddings.put(word, arr);
        count++;
      }
    }

    // <featureFactory>
    // edu.stanford.nlp.wordseg.Gale2007ChineseSegmenterFeatureFactory
    // </featureFactory>
    line = br.readLine();

    String[] featureFactoryName = line.split(" ");
    if (featureFactoryName.length < 2 || !featureFactoryName[0].equals("<featureFactory>") || !featureFactoryName[featureFactoryName.length - 1].equals("</featureFactory>")) {
      throw new RuntimeException("format error unexpected featureFactory line: " + line);
    }
    featureFactories = Generics.newArrayList();
    for (int ff = 1; ff < featureFactoryName.length - 1; ++ff) {
      FeatureFactory<IN> featureFactory = (FeatureFactory<IN>) Class.forName(featureFactoryName[1]).newInstance();
      featureFactory.init(flags);
      featureFactories.add(featureFactory);
    }

    reinit();

    // <windowSize> 2 </windowSize>
    line = br.readLine();

    String[] windowSizeName = line.split(" ");
    if (!windowSizeName[0].equals("<windowSize>") || !windowSizeName[2].equals("</windowSize>")) {
      throw new RuntimeException("format error");
    }
    windowSize = Integer.parseInt(windowSizeName[1]);

View on GitHub (pinned to 1b7edd19c4)