languagetool-org/languagetool · error · RuntimeException

Language was already instantiated, see the cause stacktrace

Error message

Language was already instantiated, see the cause stacktrace below.

What it means

Chinese is a singleton-style Language class that guards against multiple instantiation by recording a Throwable on first construction; a second constructor call throws this RuntimeException, with the first instantiation's stacktrace as the cause. This protects internal caching assumptions that Language objects are created once.

Source

Thrown at languagetool-language-modules/zh/src/main/java/org/languagetool/language/Chinese.java:49

import org.languagetool.tagging.Tagger;
import org.languagetool.tagging.zh.ChineseTagger;
import org.languagetool.tokenizers.SentenceTokenizer;
import org.languagetool.tokenizers.Tokenizer;
import org.languagetool.tokenizers.zh.ChineseSentenceTokenizer;
import org.languagetool.tokenizers.zh.ChineseWordTokenizer;

import java.io.IOException;
import java.util.*;

public class Chinese extends LanguageWithModel {
  private static final String LANGUAGE_SHORT_CODE = "zh-CN";

  private static volatile Throwable instantiationTrace;

  public Chinese() {
    Throwable trace = instantiationTrace;
    if (trace != null) {
      throw new RuntimeException("Language was already instantiated, see the cause stacktrace below.", trace);
    }
    instantiationTrace = new Throwable();
  }

  /**
   * This is a fake constructor overload for the subclasses. Public constructors can only be used by the LT itself.
   */
  protected Chinese(boolean fakeValue) {
  }


  @Override
  public String getShortCode() {
    return "zh";
  }

  @Override
  public String getName() {

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Use Languages.getLanguageForShortCode("zh") or Chinese.getInstance() instead of new Chinese()
  2. Inspect the cause stacktrace to find where the first instantiation happened
  3. Remove any custom factory code that constructs Chinese directly

Example fix

// before
Language zh = new Chinese();
// after
Language zh = Languages.getLanguageForShortCode("zh");
Defensive patterns

Strategy: type-guard

Validate before calling

Language lang = Languages.getLanguageForShortCode("zh");
if (lang instanceof Chinese) { /* reuse it */ }

Type guard

boolean chineseReady() {
    return Languages.getLanguageForShortCode("zh") instanceof Chinese;
}

Try / catch

try {
    Language zh = getOrCreateChinese();
} catch (RuntimeException e) {
    if (e.getMessage().startsWith("Language was already instantiated")) {
        zh = Languages.getLanguageForShortCode("zh"); // reuse singleton
    } else throw e;
}

Prevention

When it happens

Trigger: Calling new Chinese() a second time, e.g. code instantiating the language directly instead of using Languages.getLanguageForShortCode("zh"), or reflection/plugin code re-creating it.

Common situations: Custom server setups or tests that construct Chinese manually after LanguageTool has already registered it; copying instantiation patterns from other language classes.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06). Data as JSON: /api/errors/74a830e9ae3af161. Report an issue: GitHub.