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

The Irish language class records a stack trace in a static field on first construction; if a second Irish() instance is created it throws this RuntimeException with the first instantiation's trace as the cause. LanguageTool expects language classes to behave as singletons, and duplicate instantiation usually indicates reflective/registration misuse.

Source

Thrown at languagetool-language-modules/ga/src/main/java/org/languagetool/language/Irish.java:56

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.ResourceBundle;

/**
 * @since 4.9
 */
public class Irish extends LanguageWithModel {

  private static final String LANGUAGE_SHORT_CODE = "ga";

  private static volatile Throwable instantiationTrace;

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

  @Override
  public String getName() {
    return "Irish";
  }

  @Override
  public String[] getCountries() {
    return new String[]{"IE"};
  }
  
  @Override
  public String getShortCode() {
    return "ga";
  }

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Replace direct 'new Irish()' calls with Irish.getInstance() or Languages.getLanguageForShortCode("ga").
  2. Read the 'cause' stack trace in the exception to find the first instantiation site and remove/redirect it.
  3. In tests, reuse a shared language instance (e.g. a static field) instead of constructing one per test.
  4. Check for duplicate LanguageTool language modules on the classpath that could register Irish twice.

Example fix

// before
Language ga = new Irish();
// after
Language ga = Irish.getInstance();
Defensive patterns

Strategy: type-guard

Validate before calling

Language ga = Languages.getLanguageForShortCode("ga");
if (!(ga instanceof Irish)) throw new IllegalStateException("registry 'ga' is not Irish");

Type guard

static boolean isInstantiated() { return IrishGetInstanceTracePresent(); } // check getInstance() instead of new

Try / catch

try { lang = new Irish(); } catch (RuntimeException e) { lang = Irish.getInstance(); }

Prevention

When it happens

Trigger: Calling new Irish() directly instead of Irish.getInstance() after the class has already been instantiated once (e.g. via Languages.getLanguageForShortCode("ga")).

Common situations: Plugin or embedding code constructing the language object manually; tests creating instances outside the Languages registry; classloader duplication creating a second registry state.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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