stanfordnlp/CoreNLP · error · UnsupportedOperationException

Cannot evaluate type

Error message

Cannot evaluate type: ${typename}

What it means

SimpleCachedExpression is the base class for constant/literal expression types (strings, numbers, etc.) in Expressions. Its doEvaluation is deliberately unimplemented: evaluating a cached-type expression directly is unsupported, so it throws UnsupportedOperationException('Cannot evaluate type: <typename>'). Only concrete subclasses that override doEvaluation can be evaluated.

Solutions

  1. Override doEvaluation in your SimpleCachedExpression subclass to return the appropriate Value.
  2. Use the concrete expression factory methods (Expressions.createExpression etc.) so you get an evaluable type.
  3. Skip or special-case constant/cached nodes when iterating expressions for evaluation.
  4. Check the typename in the message to identify which expression class lacks the override.

Example fix

// before
class MyExpr extends Expressions.SimpleCachedExpression<String> {
  MyExpr(String v) { super("MY", v); }
}
// after
class MyExpr extends Expressions.SimpleCachedExpression<String> {
  MyExpr(String v) { super("MY", v); }
  @Override protected Value doEvaluation(Env env, Object... args) {
    return new Expressions.PrimitiveValue<>("MY", get());
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Only evaluate expressions whose type is evaluable
if (expr instanceof Expressions.SimpleCachedExpression
    && expr.getClass() == Expressions.SimpleCachedExpression.class) {
  throw new IllegalStateException("Refusing to evaluate non-evaluable cached expression");
}

Type guard

boolean isEvaluable(Expression e) {
  return !(e.getClass() == Expressions.SimpleCachedExpression.class);
}

Try / catch

try {
  Value v = expr.evaluate(env);
} catch (UnsupportedOperationException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("Cannot evaluate type:")) {
    logger.warning("Skipping non-evaluable expression type: " + e.getMessage());
    return null;
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling evaluate(env, args) on an Expression whose class is the plain SimpleCachedExpression (or a subclass that does not override doEvaluation), typically reached through Expressions.evaluate or Value lookups on a literal expression type.

Common situations: Custom TokensRegex expression extensions that subclass SimpleCachedExpression without overriding doEvaluation; reflection-driven evaluation over expression lists that includes non-evaluable literal nodes.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

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

      return result;
    }
  }

  /**
   * A simple implementation of an expression that is represented by a java object of type T
   *    and which also has a cached Value stored with it
   * @param <T> type of the expression object
   */
  public static class SimpleCachedExpression<T> extends SimpleExpression<T> {
    Value evaluated;
    boolean disableCaching = false;

    protected SimpleCachedExpression(String typename, T value, String... tags) {
      super(typename, value, tags);
    }

    protected Value doEvaluation(Env env, Object... args) {
      throw new UnsupportedOperationException("Cannot evaluate type: " + typename);
    }

    public Value evaluate(Env env, Object... args) {
      if (args != null) {
        return doEvaluation(env, args);
      }
      if (evaluated == null || disableCaching) {
        evaluated = doEvaluation(env, args);
      }
      return evaluated;
    }

    public boolean hasValue() {
      return (evaluated != null);
    }

    @Override
    public boolean equals(Object o) {

View on GitHub (pinned to 1b7edd19c4)