Expected behavior
Duration options like lootables.refresh-min are documented on docs.papermc.io as "a duration with a single unit e.g. 10h or 25m. Supports d, h, m, and s." So 12h should mean 43200 seconds. An empty or malformed value should give a clear config error, not a crash or a silently wrong number.
Observed/Actual behavior
The parser in io.papermc.paper.configuration.type.Duration#getSeconds (used by lootables.refresh-min, lootables.refresh-max, lootables.restrict-player-reloot-time and environment.delay-chunk-unloads-by) has a few behaviors that do not match that contract:
-
Empty or whitespace-only values throw StringIndexOutOfBoundsException on startup because of str.charAt(str.length() - 1) after stripping spaces:
StringIndexOutOfBoundsException: Index -1 out of bounds for length 0
-
The unit is taken from the last character and everything that is not a digit, dot or minus is silently stripped, so:
10H (uppercase unit) parses as 10 seconds, not 10 hours
1h30m parses as 7800 seconds, not 5400 seconds
abc parses as 0 seconds because the Double.parseDouble failure is swallowed
The wrong-value part matters in practice: if refresh-min accidentally ends up larger than refresh-max, the refill path in PaperLootableInventoryData#shouldClearLootTable calls Random#nextLong(max - min + 1) with a non-positive bound and throws.
Steps/models to reproduce
- Put this in
config/paper-world-defaults.yml:
lootables:
refresh-min: ""
- Start the server.
- Config load fails with the
StringIndexOutOfBoundsException above instead of a clean message.
For the silent wrong value:
- Set
lootables.refresh-min: 10H (capital H).
- It is treated as 10 seconds instead of 10 hours.
Plugin and Datapack List
No plugins or datapacks required, this happens during config parsing at startup.
Paper version
main branch at 6c8d413 (after 26.1.2). This is a code/config parsing issue rather than a runtime server issue, so there is no /version output to paste.
Other
I can open a PR that parses units case-insensitively, supports compound values like 1h30m, and rejects empty or invalid input with a clear error instead of crashing. Happy to grab a patch file or stack trace if useful.
Expected behavior
Duration options like
lootables.refresh-minare documented on docs.papermc.io as "a duration with a single unit e.g. 10h or 25m. Supports d, h, m, and s." So12hshould mean 43200 seconds. An empty or malformed value should give a clear config error, not a crash or a silently wrong number.Observed/Actual behavior
The parser in
io.papermc.paper.configuration.type.Duration#getSeconds(used bylootables.refresh-min,lootables.refresh-max,lootables.restrict-player-reloot-timeandenvironment.delay-chunk-unloads-by) has a few behaviors that do not match that contract:Empty or whitespace-only values throw
StringIndexOutOfBoundsExceptionon startup because ofstr.charAt(str.length() - 1)after stripping spaces:StringIndexOutOfBoundsException: Index -1 out of bounds for length 0The unit is taken from the last character and everything that is not a digit, dot or minus is silently stripped, so:
10H(uppercase unit) parses as 10 seconds, not 10 hours1h30mparses as 7800 seconds, not 5400 secondsabcparses as 0 seconds because theDouble.parseDoublefailure is swallowedThe wrong-value part matters in practice: if
refresh-minaccidentally ends up larger thanrefresh-max, the refill path inPaperLootableInventoryData#shouldClearLootTablecallsRandom#nextLong(max - min + 1)with a non-positive bound and throws.Steps/models to reproduce
config/paper-world-defaults.yml:StringIndexOutOfBoundsExceptionabove instead of a clean message.For the silent wrong value:
lootables.refresh-min: 10H(capital H).Plugin and Datapack List
No plugins or datapacks required, this happens during config parsing at startup.
Paper version
main branch at 6c8d413 (after 26.1.2). This is a code/config parsing issue rather than a runtime server issue, so there is no
/versionoutput to paste.Other
I can open a PR that parses units case-insensitively, supports compound values like
1h30m, and rejects empty or invalid input with a clear error instead of crashing. Happy to grab a patch file or stack trace if useful.