{"record":{"id":"ac7ca80e76d46c02","repo":"languagetool-org/languagetool","slug":"language-was-already-instantiated-see-the-cause-s-ac7ca8","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/fr/src/main/java/org/languagetool/language/SwissFrench.java","lineNumber":32,"sourceCode":" * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301\n * USA\n */\npackage org.languagetool.language;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class SwissFrench extends French {\n\n  private static volatile Throwable instantiationTrace;\n\n  public SwissFrench() {\n    super(true);\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 \"French (Switzerland)\";\n  }\n\n  @Override\n  public String[] getCountries() {\n    return new String[] { \"CH\" };\n  }\n\n  @Override\n  public List<String> getDefaultDisabledRulesForVariant() {\n    List<String> rules = Collections.singletonList(\"DOUBLER_UNE_CLASSE\");\n    return rules;","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-language-modules/fr/src/main/java/org/languagetool/language/SwissFrench.java#L14-L50","documentation":"SwissFrench's constructor is a singleton guard identical to the other French variants: the Language object must only be instantiated once through LT's language registry. On a second instantiation it throws RuntimeException, attaching the stack trace recorded at the first instantiation as the cause.","triggerScenarios":"Calling new SwissFrench() directly instead of Languages.getLanguageForShortCode(\"fr-CH\")/getInstance; reflective instantiation by a framework; duplicate classloaders each constructing the language.","commonSituations":"Application code constructing language objects manually; serialization/deserialization creating new instances; test harnesses instantiating the language class.","solutions":["Use Languages.getLanguageForShortCode(\"fr-CH\") instead of the constructor.","Use the exception's cause trace to find the initial instantiation and remove the duplicate creation path.","Ensure a single classloader loads the French language module."],"exampleFix":"// before\nLanguage lang = new SwissFrench();\n// after\nLanguage lang = Languages.getLanguageForShortCode(\"fr-CH\");","handlingStrategy":"validation","validationCode":"// Obtain the singleton instead of constructing:\nLanguage lang = Languages.getLanguageForShortCode(\"fr-CH\");","typeGuard":null,"tryCatchPattern":"try {\n  new SwissFrench();\n} catch (RuntimeException e) {\n  e.getCause().printStackTrace(); // shows first instantiation site\n}","preventionTips":["Always fetch SwissFrench via the language registry","Inspect the cause trace to locate the first instantiation","Avoid reflective or serialization-based construction of Language objects"],"tags":["java","languagetool","singleton","instantiation"],"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"}