stanfordnlp/CoreNLP · error · RuntimeException

Unknown class

Error message

Unknown class ${className}

What it means

When a TYPE "CLASS"/annotation-key value is evaluated, the stored string is loaded via Class.forName. If no class with that name is on the classpath, ClassNotFoundException is wrapped in this RuntimeException with the offending class name. It exists to fail fast on unresolvable class names inside TokensRegex expressions.

Solutions

  1. Use the fully qualified class name including package and $ for inner classes (e.g. edu.stanford.nlp.ling.CoreAnnotations$Tokens).
  2. Verify the class exists on the runtime classpath (deployment jar includes custom classes).
  3. Check for package/class renames in your CoreNLP version and update the name, or pin the older version.
  4. Pre-test with Class.forName(name) in setup code to validate all class names used in rules at startup.

Example fix

// before
(CLASS) { type: "CLASS", value: "CoreAnnotations$TokensAnnotation" }
// after
(CLASS) { type: "CLASS", value: "edu.stanford.nlp.ling.CoreAnnotations$TokensAnnotation" }
Defensive patterns

Strategy: validation

Validate before calling

static void validateClassName(String name) {
  try { Class.forName(name); }
  catch (ClassNotFoundException e) { throw new IllegalStateException("Class used in rule not on classpath: " + name); }
}

Type guard

static boolean resolvableClass(String name) {
  try { Class.forName(name); return true; } catch (ClassNotFoundException e) { return false; }
}

Try / catch

try { Value v = expr.evaluate(env, args); }
catch (RuntimeException ex) {
  if (ex.getMessage().startsWith("Unknown class")) {
    log.error("Bad class name in rule: " + ex.getMessage(), ex);
  }
  throw ex;
}

Prevention

When it happens

Trigger: Evaluating a composite/typed value with TYPE "CLASS" and a class name string that is misspelled, not fully qualified (missing package), or not on the runtime classpath; referencing CoreNLP classes whose packages changed across versions.

Common situations: Rules specifying edu.stanford.nlp.ling.CoreAnnotations$SomeAnnotation keys; typos in inner-class $ separators; custom annotation classes not included in the deployment jar; package refactors between CoreNLP versions.

Related errors


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

Appendix: source

Thrown at src/edu/stanford/nlp/ling/tokensregex/types/Expressions.java:1314

                  return new PrimitiveValue<>(typeName, m.invoke(typeValue.get(), evaluatedCv));
                } catch (InvocationTargetException | IllegalAccessException ex) {
                  throw new RuntimeException("Cannot instantiate " + c, ex);
                }
              } catch (NoSuchMethodException ex) {}
            }
          }
        } else if (typeValue != null && typeValue.get() instanceof String) {
          String typeName = (String) typeValue.get();
          // Predefined types:
          Expression valueField = cv.value.get("value");
          Value value = valueField.evaluate(env, args);
          switch (typeName) {
            case TYPE_ANNOTATION_KEY: {
              String className = (String) value.get();
              try {
                return new PrimitiveValue<Class>(TYPE_ANNOTATION_KEY, Class.forName(className));
              } catch (ClassNotFoundException ex) {
                throw new RuntimeException("Unknown class " + className, ex);
              }
            }
            case TYPE_CLASS: {
              String className = (String) value.get();
              try {
                return new PrimitiveValue<Class>(TYPE_CLASS, Class.forName(className));
              } catch (ClassNotFoundException ex) {
                throw new RuntimeException("Unknown class " + className, ex);
              }
            }
            case TYPE_STRING:
              return new PrimitiveValue<>(TYPE_STRING, (String) value.get());
            case TYPE_REGEX:
              return new RegexValue((String) value.get());
            /* } else if (TYPE_TOKEN_REGEX.equals(type)) {
       return new PrimitiveValue<TokenSequencePattern>(TYPE_TOKEN_REGEX, (TokenSequencePattern) value.get()); */
            case TYPE_NUMBER:
              if (value.get() instanceof Number) {

View on GitHub (pinned to 1b7edd19c4)