When working with LibGDX, everything might seem smooth during development until you export your game as a .jar
file.
That’s exactly what happened to me. My small Java game ran flawlessly inside Eclipse, but when I compiled it and ran the .jar
, it crashed with a runtime error:
The Error
Error reading file: ui/menuSkin.json
Stack trace:
com.badlogic.gdx.scenes.scene2d.ui.Skin.load(Skin.java:96)
com.badlogic.gdx.scenes.scene2d.ui.Skin.<init>(Skin.java:81)
com.castell.randomcastle.screens.BasicsScreen.show(BasicsScreen.java:105)
And the culprit
skin = new Skin(Gdx.files.internal("ui/menuSkin.json"), new TextureAtlas("ui/atlas.pack"))
What Caused the Error
After a few hours of debugging, I learned something important:
The issue wasn’t the content of the JSON file it was that the file couldn’t be found in the compiled .jar
.
LibGDX uses Gdx.files.internal()
to reference files located in the assets/
folder of the core project. In Eclipse, this works seamlessly because assets are linked properly at runtime.
But in a compiled .jar
:
If the assets
folder isn’t properly included, the game can’t find your files and crashes.
How to Fix It
Make sure:
- Your
assets/
directory is in the right place (core/assets/
) - It is explicitly included in your
.jar
export
Using Gradle
If you’re using Gradle, this is the cleanest solution.
Add this line to your desktop/build.gradle
:
sourceSets.main.resources.srcDirs += [rootProject.file("core/assets").path]
Rebuild with Gradle:
./gradlew desktop:dist
Your .jar
file in desktop/build/libs
should now include the assets/
folder and all necessary files.
Adding Robustness
To improve the code, let’s make it more resilient:
- Catch asset-loading errors
- Log missing files clearly
- Use a fallback skin when possible
public class BasicsScreen extends ScreenAdapter {
private Skin skin;
@Override
public void show() {
try {
FileHandle skinFile = Gdx.files.internal("ui/menuSkin.json");
FileHandle atlasFile = Gdx.files.internal("ui/atlas.pack");
if (!skinFile.exists() || !atlasFile.exists()) {
throw new GdxRuntimeException("Required UI files not found.");
}
skin = new Skin(skinFile, new TextureAtlas(atlasFile));
} catch (Exception e) {
Gdx.app.error("SkinLoading", "Failed to load UI skin: " + e.getMessage(), e);
// Attempt fallback
try {
Gdx.app.log("SkinLoading", "Loading fallback skin.");
skin = new Skin(Gdx.files.internal("defaultSkin/uiskin.json")); // Ensure this file exists
} catch (Exception fallbackError) {
Gdx.app.error("SkinLoading", "Fallback skin also failed!", fallbackError);
}
}
}
}
Why This Practice Matter
Improves debugging clarity
Prevents game-breaking crashes
Prepares your game for real-world deployment
Builds habits around defensive programming
Final Thought
If your game runs perfectly in your IDE but crashes as a compiled .jar
, the root cause is usually missing or misconfigured assets. Often, it’s either an incorrect file path or the asset wasn’t bundled during the export. To avoid these headaches, make sure your build process (especially with Gradle) is set up to include all required resources. Always test your compiled builds, and add fallback logic for missing files to make your game more robust.