Skip to content

TilesetLoader.loadImage() fails with "Image dimensions must be positive" when tiles have custom properties #1461

@omicreativedev

Description

@omicreativedev

Describe the bug
TilesetLoader.loadImage() fails with "Image dimensions must be positive" when tiles have custom properties.
The objective was to use Tiled Map Editor to make the JSON map information for use with FXGL.
I admit, I'm new to this so I'm not sure I did it right. Im going to use an object layer instead, but I thought someone might want to look at this anyway

To Reproduce
This happens when using TiledMapEditor (https://www.mapeditor.org/) to generate a map. When using a map with an embedded (or external) tileset, and adding a custom property to the tile, such that the rendered JSON appears to have:

<tile id="1">
   <properties>
    <property name="blocking" type="bool" value="true"/>
    <property name="type" value="map_tile_wall"/>
   </properties>
  </tile>

The map no longer parses.

Expected behavior
I expected the map to parse.
When using a .tmx without any custom properties, it works.

Runtime info(please complete the following information):
Windows 11 Home
Using Java: JDK 21 (LTS), JavaFX: 21.0.1, FXGL: 21.1, Tiled Map Editor: 1.11.2, Maven 3.9.5, Eclipse Version: 2025-12 (4.38.0)

Attach log associated with the bug (can be found in "logs/")
[INFO] Scanning for projects...
[INFO]
[INFO] �[1m-------------------------< �[0;36mcom.mygame:MyGame�[0;1m >--------------------------�[m
[INFO] �[1mBuilding MyGame 0.0.1-SNAPSHOT�[m
[INFO] from pom.xml
[INFO] �[1m--------------------------------[ jar ]---------------------------------�[m
[WARNING] 6 problems were encountered while building the effective model for org.openjfx:javafx-fxml:jar:21.0.1 during dependency collection step for project (use -X to see details)
[INFO]
[INFO] �[1m--- �[0;32mclean:3.2.0:clean�[m �[1m(default-clean)�[m @ �[36mMyGame�[0;1m ---�[m
[INFO] Deleting D:\Repos\MyGame\target
[INFO]
[INFO] �[1m>>> �[0;32mjavafx:0.0.8:run�[m �[1m(default-cli)�[0;1m > �[0;1mprocess-classes�[m @ �[36mMyGame�[0;1m >>>�[m
[INFO]
[INFO] �[1m--- �[0;32mresources:3.3.1:resources�[m �[1m(default-resources)�[m @ �[36mMyGame�[0;1m ---�[m
[INFO] Copying 17 resources from src\main\resources to target\classes
[INFO]
[INFO] �[1m--- �[0;32mcompiler:3.13.0:compile�[m �[1m(default-compile)�[m @ �[36mMyGame�[0;1m ---�[m
[INFO] Recompiling the module because of �[1mchanged source code�[m.
[INFO] Compiling 15 source files with javac [debug release 21 module-path] to target\classes
[INFO]
[INFO] �[1m<<< �[0;32mjavafx:0.0.8:run�[m �[1m(default-cli)�[0;1m < �[0;1mprocess-classes�[m @ �[36mMyGame�[0;1m <<<�[m
[INFO]
[INFO]
[INFO] �[1m--- �[0;32mjavafx:0.0.8:run�[m �[1m(default-cli)�[m @ �[36mMyGame�[0;1m ---�[m
[WARNING] Module name not found in . Module name will be assumed from module-info.java
10:04:04.959 [JavaFX Application Thread] INFO Engine - FXGL-21.1 (27.03.2024 07.52) on WINDOWS (J:21.0.10 FX:21.0.1)
10:04:04.960 [JavaFX Application Thread] INFO Engine - Source code and latest versions at: https://github.com/AlmasB/FXGL
10:04:04.961 [JavaFX Application Thread] INFO Engine - Ask questions and discuss at: https://github.com/AlmasB/FXGL/discussions
10:04:04.961 [JavaFX Application Thread] INFO Engine - Join the FXGL chat at: https://gitter.im/AlmasB/FXGL
10:04:05.951 [FXGL Background Thread 1 ] INFO FXGLApplication - FXGL initialization took: 0.590 sec
10:04:06.129 [FXGL Background Thread 4 ] WARN TMXLevelLoader - TiledMap generated from 1.11.2. Supported version: 1.9.0. Some features may not be parsed fully.
10:04:06.203 [FXGL Background Thread 4 ] WARN TilesetLoader - file:/D:/Repos/MyGame/target/classes/assets/levels/ cannot be loaded
10:04:06.258 [FXGL Background Thread 4 ] WARN TilesetLoader - cannot be loaded using mapURL=file:/D:/Repos/MyGame/target/classes/assets/levels/level_01.tmx
java.lang.IllegalArgumentException: Image dimensions must be positive (w,h > 0)
at javafx.graphics@21.0.1/javafx.scene.image.Image.(Image.java:743)
at javafx.graphics@21.0.1/javafx.scene.image.WritableImage.(WritableImage.java:77)
at com.almasb.fxgl.core@21.1/com.almasb.fxgl.texture.ImagesKt.resize(Images.kt:143)
at com.almasb.fxgl.core@21.1/com.almasb.fxgl.texture.ImagesKt.resize(Images.kt:127)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TilesetLoader.loadImage(TilesetLoader.kt:440)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TilesetLoader.loadView(TilesetLoader.kt:156)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TMXLevelLoader$createTileLayerEntities$1.invoke(TMXLevelLoader.kt:99)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TMXLevelLoader$createTileLayerEntities$1.invoke(TMXLevelLoader.kt:88)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TMXLevelLoader.createTileLayerEntities$lambda$3(TMXLevelLoader.kt:88)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TMXLevelLoader.createTileLayerEntities(TMXLevelLoader.kt:116)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TMXLevelLoader.load(TMXLevelLoader.kt:58)
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.app.services.FXGLAssetLoaderService.loadLevel(FXGLAssetLoaderService.kt:449)
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.dsl.FXGL$Companion.setLevelFromMap(FXGL.kt:643)
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.dsl.FXGL.setLevelFromMap(FXGL.kt)
at com.mygame@0.0.1-SNAPSHOT/com.mygame.MyGameApp.initGame(MyGameApp.java:89)
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.app.FXGLApplication$InitAppTask.initGame(FXGLApplication.kt:343)
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.app.FXGLApplication$InitAppTask.call(FXGLApplication.kt:321)
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.app.FXGLApplication$InitAppTask.call(FXGLApplication.kt:313)
at javafx.graphics@21.0.1/javafx.concurrent.Task$TaskCallable.call(Task.java:1399)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
at java.base/java.lang.Thread.run(Thread.java:1583)

10:04:06.259 [FXGL Background Thread 4 ] WARN TMXLevelLoader - Parse error
java.lang.IllegalArgumentException: Image dimensions must be positive (w,h > 0)
at javafx.graphics@21.0.1/javafx.scene.image.Image.(Image.java:743)
at javafx.graphics@21.0.1/javafx.scene.image.WritableImage.(WritableImage.java:77)
at com.almasb.fxgl.core@21.1/com.almasb.fxgl.texture.ImagesKt.resize(Images.kt:143)
at com.almasb.fxgl.core@21.1/com.almasb.fxgl.texture.ImagesKt.resize(Images.kt:127)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TilesetLoader.loadImage(TilesetLoader.kt:448)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TilesetLoader.loadView(TilesetLoader.kt:156)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TMXLevelLoader$createTileLayerEntities$1.invoke(TMXLevelLoader.kt:99)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TMXLevelLoader$createTileLayerEntities$1.invoke(TMXLevelLoader.kt:88)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TMXLevelLoader.createTileLayerEntities$lambda$3(TMXLevelLoader.kt:88)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TMXLevelLoader.createTileLayerEntities(TMXLevelLoader.kt:116)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TMXLevelLoader.load(TMXLevelLoader.kt:58)
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.app.services.FXGLAssetLoaderService.loadLevel(FXGLAssetLoaderService.kt:449)
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.dsl.FXGL$Companion.setLevelFromMap(FXGL.kt:643)
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.dsl.FXGL.setLevelFromMap(FXGL.kt)
at com.mygame@0.0.1-SNAPSHOT/com.mygame.MyGameApp.initGame(MyGameApp.java:89)
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.app.FXGLApplication$InitAppTask.initGame(FXGLApplication.kt:343)
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.app.FXGLApplication$InitAppTask.call(FXGLApplication.kt:321)
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.app.FXGLApplication$InitAppTask.call(FXGLApplication.kt:313)
at javafx.graphics@21.0.1/javafx.concurrent.Task$TaskCallable.call(Task.java:1399)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
at java.base/java.lang.Thread.run(Thread.java:1583)

10:04:06.262 [JavaFX Application Thread] FATAL FXGLApplication - Uncaught Exception:
java.lang.RuntimeException: Initialization failed
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.app.FXGLApplication$InitAppTask.failed(FXGLApplication.kt:347)
at javafx.graphics@21.0.1/javafx.concurrent.Task.setState(Task.java:710)
at javafx.graphics@21.0.1/javafx.concurrent.Task$TaskCallable.lambda$call$2(Task.java:1429)
at javafx.graphics@21.0.1/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:456)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
at javafx.graphics@21.0.1/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:455)
at javafx.graphics@21.0.1/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at javafx.graphics@21.0.1/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics@21.0.1/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:185)
at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: com.almasb.fxgl.entity.level.LevelLoadingException: Image dimensions must be positive (w,h > 0)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TMXLevelLoader.load(TMXLevelLoader.kt:77)
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.app.services.FXGLAssetLoaderService.loadLevel(FXGLAssetLoaderService.kt:449)
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.dsl.FXGL$Companion.setLevelFromMap(FXGL.kt:643)
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.dsl.FXGL.setLevelFromMap(FXGL.kt)
at com.mygame@0.0.1-SNAPSHOT/com.mygame.MyGameApp.initGame(MyGameApp.java:89)
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.app.FXGLApplication$InitAppTask.initGame(FXGLApplication.kt:343)
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.app.FXGLApplication$InitAppTask.call(FXGLApplication.kt:321)
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.app.FXGLApplication$InitAppTask.call(FXGLApplication.kt:313)
at javafx.graphics@21.0.1/javafx.concurrent.Task$TaskCallable.call(Task.java:1399)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
... 1 more
Caused by: java.lang.IllegalArgumentException: Image dimensions must be positive (w,h > 0)
at javafx.graphics@21.0.1/javafx.scene.image.Image.(Image.java:743)
at javafx.graphics@21.0.1/javafx.scene.image.WritableImage.(WritableImage.java:77)
at com.almasb.fxgl.core@21.1/com.almasb.fxgl.texture.ImagesKt.resize(Images.kt:143)
at com.almasb.fxgl.core@21.1/com.almasb.fxgl.texture.ImagesKt.resize(Images.kt:127)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TilesetLoader.loadImage(TilesetLoader.kt:448)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TilesetLoader.loadView(TilesetLoader.kt:156)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TMXLevelLoader$createTileLayerEntities$1.invoke(TMXLevelLoader.kt:99)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TMXLevelLoader$createTileLayerEntities$1.invoke(TMXLevelLoader.kt:88)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TMXLevelLoader.createTileLayerEntities$lambda$3(TMXLevelLoader.kt:88)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TMXLevelLoader.createTileLayerEntities(TMXLevelLoader.kt:116)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TMXLevelLoader.load(TMXLevelLoader.kt:58)
... 14 more

10:04:06.262 [JavaFX Application Thread] FATAL FXGLApplication - Application will now exit
10:04:06.774 [FXGL Background Thread 2 ] INFO UpdaterService - Your current version: 21.1
10:04:06.774 [FXGL Background Thread 2 ] INFO UpdaterService - Latest stable version: 25
[INFO] �[1m------------------------------------------------------------------------�[m
[INFO] �[1;32mBUILD SUCCESS�[m
[INFO] �[1m------------------------------------------------------------------------�[m
[INFO] Total time: 18.364 s
[INFO] Finished at: 2026-02-08T10:04:18-05:00
[INFO] �[1m------------------------------------------------------------------------�[m

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions