{"record":{"id":"a3670bfade25a44f","repo":"languagetool-org/languagetool","slug":"language-was-already-instantiated-see-the-cause-s-a3670b","errorCode":null,"errorMessage":"Language was already instantiated, see the cause stacktrace below.","messagePattern":"Language was already instantiated, see the cause stacktrace below\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"languagetool-language-modules/ga/src/main/java/org/languagetool/language/Irish.java","lineNumber":56,"sourceCode":"import java.io.IOException;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.ResourceBundle;\n\n/**\n * @since 4.9\n */\npublic class Irish extends LanguageWithModel {\n\n  private static final String LANGUAGE_SHORT_CODE = \"ga\";\n\n  private static volatile Throwable instantiationTrace;\n\n  public Irish() {\n    Throwable trace = instantiationTrace;\n    if (trace != null) {\n      throw new RuntimeException(\"Language was already instantiated, see the cause stacktrace below.\", trace);\n    }\n    instantiationTrace = new Throwable();\n  }\n\n  @Override\n  public String getName() {\n    return \"Irish\";\n  }\n\n  @Override\n  public String[] getCountries() {\n    return new String[]{\"IE\"};\n  }\n  \n  @Override\n  public String getShortCode() {\n    return \"ga\";\n  }","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-language-modules/ga/src/main/java/org/languagetool/language/Irish.java#L38-L74","documentation":"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.","triggerScenarios":"Calling new Irish() directly instead of Irish.getInstance() after the class has already been instantiated once (e.g. via Languages.getLanguageForShortCode(\"ga\")).","commonSituations":"Plugin or embedding code constructing the language object manually; tests creating instances outside the Languages registry; classloader duplication creating a second registry state.","solutions":["Replace direct 'new Irish()' calls with Irish.getInstance() or Languages.getLanguageForShortCode(\"ga\").","Read the 'cause' stack trace in the exception to find the first instantiation site and remove/redirect it.","In tests, reuse a shared language instance (e.g. a static field) instead of constructing one per test.","Check for duplicate LanguageTool language modules on the classpath that could register Irish twice."],"exampleFix":"// before\nLanguage ga = new Irish();\n// after\nLanguage ga = Irish.getInstance();","handlingStrategy":"type-guard","validationCode":"Language ga = Languages.getLanguageForShortCode(\"ga\");\nif (!(ga instanceof Irish)) throw new IllegalStateException(\"registry 'ga' is not Irish\");","typeGuard":"static boolean isInstantiated() { return IrishGetInstanceTracePresent(); } // check getInstance() instead of new","tryCatchPattern":"try { lang = new Irish(); } catch (RuntimeException e) { lang = Irish.getInstance(); }","preventionTips":["Never construct Language classes with 'new' — always use getInstance()/Languages registry","Share one language instance across tests via a static field","Read the exception's cause trace to locate the first instantiation"],"tags":["java","languagetool","singleton","irish"],"backgroundTag":"invalid-state-transition","analyzedSha":"2e990059ce67d5e2a0f7f7ca5d31160c6709df4b","analyzedAt":"2026-09-06T09:20:17.015Z","contentChangedAt":"2026-09-06T09:20:17.015Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}