infinilabs/analysis-ik · error · IllegalStateException

ik dict has not been initialized yet, please call initial me

Error message

ik dict has not been initialized yet, please call initial method first.

What it means

Dictionary is a singleton that must be primed by the static method Dictionary.initial(Configuration) before any dictionary-dependent API runs; getSingleton() throws IllegalStateException when that initialization has not happened. Most library code paths (CJKSegmenter, CN_QuantifierSegmenter, AnalyzeContext stopword filtering, Monitor reload) call Dictionary.getSingleton() internally, so the exception usually surfaces from inside a tokenization call rather than from user code directly.

Source

Thrown at core/src/main/java/org/wltea/analyzer/dic/Dictionary.java:293

				}
			}
		}
		return remoteExtStopWordDictFiles;
	}

	private String getDictRoot() {
		return conf_dir.toAbsolutePath().toString();
	}


	/**
	 * 获取词典单子实例
	 * 
	 * @return Dictionary 单例对象
	 */
	public static Dictionary getSingleton() {
		if (singleton == null) {
			throw new IllegalStateException("ik dict has not been initialized yet, please call initial method first.");
		}
		return singleton;
	}


	/**
	 * 批量加载新词条
	 * 
	 * @param words
	 *            Collection<String>词条列表
	 */
	public void addWords(Collection<String> words) {
		if (words != null) {
			for (String word : words) {
				if (word != null) {
					// 批量加载词条到主内存词典中
					singleton._MainDict.fillSegment(word.trim().toCharArray());
				}

View on GitHub (pinned to 6d2d70fd1a)

Solutions

  1. Call Dictionary.initial(DefaultConfig.getInstance()) once at application/test startup (static initializer, @BeforeAll, or context-listener) before the first IKAnalyzer/IKTokenizer use
  2. For custom configuration (ext/remote dictionaries), build your Configuration (e.g. DefaultConfig with a known conf dir) and pass that to initial instead of the default
  3. If the error appears mid-run in a container environment, check for duplicate IK jars across classloaders and keep exactly one copy so the initialized singleton and the consumers are the same class
  4. Wrap first-use in a small ensureInitialized() helper so every entry point cheaply guarantees initial was called

Example fix

// before — throws IllegalStateException on first token
IKAnalyzer analyzer = new IKAnalyzer(true);
analyzer.tokenize(...);

// after — initialize the singleton once before first use
Dictionary.initial(DefaultConfig.getInstance());
IKAnalyzer analyzer = new IKAnalyzer(true);
analyzer.tokenize(...);
Defensive patterns

Strategy: validation

Validate before calling

private static volatile boolean ikInitialized;
static void ensureIkInitialized() {
    if (!ikInitialized) {
        synchronized (IkInit.class) {
            if (!ikInitialized) {
                Dictionary.initial(DefaultConfig.getInstance());
                ikInitialized = true;
            }
        }
    }
}
// call ensureIkInitialized() before creating IKAnalyzer or touching Dictionary

Try / catch

try {
    Dictionary.getSingleton().addWords(words);
} catch (IllegalStateException e) {
    if (e.getMessage() != null && e.getMessage().contains("not been initialized")) {
        Dictionary.initial(DefaultConfig.getInstance());
        Dictionary.getSingleton().addWords(words); // retry once after init
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling Dictionary.getSingleton(), or any API that reaches it — new IKAnalyzer(...)/IKTokenizer tokenization, addWords/removeWords, Dictionary.matchInMainDict — before Dictionary.initial(cfg) has run anywhere in the JVM. Because singleton is a static field, this also happens in tests that fork/reset state or when a classloader boundary creates a second, uninitialized copy of the Dictionary class (e.g. some plugin containers).

Common situations: Upgrading from a classic IK Analyzer version where getSingleton() lazily self-initialized with DefaultConfig to this fork, where initialization is explicit and lazy init was removed; unit tests that construct an IKAnalyzer without the shared TestUtils.initial step; embedding IK in an application server/OSGi bundle where a child classloader loads a fresh Dictionary class after the parent-initialized one; multi-threaded first use racing initialization is safe (initial is synchronized) but zero use before first tokenization is not.

Related errors


AI-assisted analysis of infinilabs/analysis-ik@6d2d70fd1a (2026-08-14). Data as JSON: /api/errors/aba2facb27e123e9. Report an issue: GitHub.