stanfordnlp/CoreNLP · error · IllegalArgumentException

SpanishLexer: the invertible option requires a…

Error message

SpanishLexer: the invertible option requires a CoreLabelTokenFactory

What it means

SpanishLexer supports the 'invertible' option only with a CoreLabelTokenFactory, since invertibility stores original character offsets in CoreLabel fields. If invertible=true and the provided TokenFactory is not a CoreLabelTokenFactory, the constructor throws this IllegalArgumentException immediately.

Solutions

  1. Pass a CoreLabelTokenFactory whenever invertible=true.
  2. Drop the invertible option if you do not need original-text offsets.
  3. Make any custom factory extend CoreLabelTokenFactory so the instanceof check succeeds.
  4. Check (tf instanceof CoreLabelTokenFactory) before enabling invertible in code that builds options dynamically.

Example fix

// before
lex = new SpanishLexer(reader, new WordTokenFactory(), invertibleOptions);
// after
lex = new SpanishLexer(reader, new CoreLabelTokenFactory(), invertibleOptions);
Defensive patterns

Strategy: validation

Validate before calling

boolean invertible = Boolean.parseBoolean(options.getOrDefault("invertible", "false"));
if (invertible && !(tf instanceof CoreLabelTokenFactory))
  throw new IllegalArgumentException("invertible requires CoreLabelTokenFactory");

Type guard

boolean isCoreLabelFactory(TokenFactory tf) { return tf instanceof CoreLabelTokenFactory; }

Try / catch

try {
  lex = new SpanishLexer(reader, tf, options);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("invertible option requires")) {
    lex = new SpanishLexer(reader, new CoreLabelTokenFactory(), options);
  } else throw e;
}

Prevention

When it happens

Trigger: new SpanishLexer(reader, nonCoreLabelTokenFactory, options) where options sets invertible=true; e.g. passing WordTokenFactory while requesting invertible tokenization for offset recovery.

Common situations: Enabling invertible in CoreNLP pipeline properties while using a default or custom factory; copying lexer setups from code that used a different TokenFactory; custom factories that do not subclass CoreLabelTokenFactory.

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/1bf1fbf23e42e7d6. Report an issue: GitHub.

Appendix: source

Thrown at src/edu/stanford/nlp/international/spanish/process/SpanishLexer.flex:186

              case "firstKeep":
                untokenizable = UntokenizableOptions.FIRST_KEEP;
                break;
              case "allKeep":
                untokenizable = UntokenizableOptions.ALL_KEEP;
                break;
              default:
                throw new IllegalArgumentException("SpanishLexer: Invalid option value in constructor: " + key + ": " + value);
            }
          } else if ("strictTreebank3".equals(key)) {
            strictTreebank3 = val;
          } else {
            throw new IllegalArgumentException(String.format("%s: Invalid options key in constructor: %s%n", this.getClass().getName(), key));
          }
        }
        // this.seenUntokenizableCharacter = false; // unnecessary, it's default initialized
        if (invertible) {
          if ( ! (tf instanceof CoreLabelTokenFactory)) {
            throw new IllegalArgumentException("SpanishLexer: the invertible option requires a CoreLabelTokenFactory");
          }
          prevWord = (CoreLabel) tf.makeToken("", 0, 0);
          prevWordAfter = new StringBuilder();
        }
      }


      /** Turn on to find out how things were tokenized. */
      private static final boolean DEBUG = false;

      /** A logger for this class */
      private static final Redwood.RedwoodChannels logger = Redwood.channels(SpanishLexer.class);

      private LexedTokenFactory<?> tokenFactory;
      private CoreLabel prevWord;
      private StringBuilder prevWordAfter;
      private boolean seenUntokenizableCharacter;
      private enum UntokenizableOptions { NONE_DELETE, FIRST_DELETE, ALL_DELETE, NONE_KEEP, FIRST_KEEP, ALL_KEEP }

View on GitHub (pinned to 1b7edd19c4)