Grasscutters/Grasscutter · critical · RuntimeException
Unable to load the primary, fallback, and 'en-US' language f
Error message
Unable to load the primary, fallback, and 'en-US' language files.
What it means
Language.getLanguageTextMapKey / load logic tries the requested language file, then a fallback, then the bundled /languages/en-US.json; if the en-US resource stream is also null, it throws this RuntimeException. This means the language resource files are not on the classpath at all — a broken installation, not a bad user config.
Source
Thrown at src/main/java/emu/grasscutter/utils/lang/Language.java:218
return new LanguageStreamDescription(actualLanguageCode, null);
}
file = Grasscutter.class.getResourceAsStream("/languages/" + fallback);
}
if (file == null) { // Fallback the fallback language.
Grasscutter.getLogger()
.warn("Failed to load language file: " + fallback + ", falling back to: en-US.json");
actualLanguageCode = "en-US";
if (cachedLanguages.containsKey(actualLanguageCode)) {
return new LanguageStreamDescription(actualLanguageCode, null);
}
file = Grasscutter.class.getResourceAsStream("/languages/en-US.json");
}
if (file == null)
throw new RuntimeException(
"Unable to load the primary, fallback, and 'en-US' language files.");
return new LanguageStreamDescription(actualLanguageCode, file);
}
private static Int2ObjectMap<String> loadTextMapFile(String language, IntSet nameHashes) {
Int2ObjectMap<String> output = new Int2ObjectOpenHashMap<>();
try (BufferedReader file =
Files.newBufferedReader(
getResourcePath("TextMap/TextMap" + language + ".json"), StandardCharsets.UTF_8)) {
Matcher matcher = textMapKeyValueRegex.matcher("");
return new Int2ObjectOpenHashMap<>(
file.lines()
.sequential()
.map(matcher::reset) // Side effects, but it's faster than making a new one
.filter(Matcher::find)
.filter(
m ->View on GitHub (pinned to f373827a83)
Solutions
- Rebuild the project so resources are packaged: run the gradle build (e.g. ./gradlew build) and launch the produced jar
- Verify src/main/resources/languages/en-US.json exists in the repo and inside the jar (jar tf grasscutter.jar | grep languages)
- If running from an IDE/exploded classpath, ensure src/main/resources is marked as a resources root
- Check any -DlanguageCode or config language value is not the root cause, though fixing the classpath is the real fix
Example fix
// before (launching bare classes without resources on classpath) java -cp classes emu.grasscutter.Grasscutter // after ./gradlew build && java -jar grasscutter.jar
Defensive patterns
Strategy: fallback
Validate before calling
boolean languageResourcesPresent() {
return Grasscutter.class.getResource("/languages/en-US.json") != null;
} Type guard
null
Try / catch
try {
Language lang = Language.load("en-US");
} catch (RuntimeException e) {
logger.fatal("Language resources missing from classpath; rebuild the jar.");
System.exit(1);
} Prevention
- Always build and run via the gradle jar, not bare class directories
- Verify en-US.json exists under src/main/resources/languages in the packaged artifact
- Add a startup check that getResource("/languages/en-US.json") != null
- Don't delete or rename resource files when editing language configs
When it happens
Trigger: Calling Language.load/getTextMap (or starting Grasscutter) when none of the requested language, fallback, and embedded en-US.json resources resolve, i.e. Grasscutter.class.getResourceAsStream("/languages/en-US.json") returns null.
Common situations: Running from a partially built jar where resources weren't packaged; deleting or renaming src/main/resources/languages; launching classes without the resources directory on the classpath; corrupted gradle build output.
Related errors
AI-assisted analysis of Grasscutters/Grasscutter@f373827a83 (2026-09-03).
Data as JSON: /api/errors/8e716155a486939e.
Report an issue: GitHub.