Negative skillIncreasesForAttribute value causes "GameSetting 'iLevelUp-2Mult' not found" every frame
Summary
If a player's skill increase counter for an attribute is negative, NpcStats::getLevelupAttributeMultiplier builds a game setting name that doesn't exist, such as iLevelUp-2Mult, and the lookup throws. The stats window calls this function in onFrame, so the error is logged every frame:
[04:33:09.210 E] Error in frame: GameSetting '"iLevelUp-2Mult"' not foundA mod user reported this. Lua can set the counter to a negative value, and neither the setter nor the getter checks for it.
Tested against master bb9e0ce2a9 (2026-09-15); also present in 0.51.
Cause
apps/openmw/mwmechanics/npcstats.cpp:259-271:
int MWMechanics::NpcStats::getLevelupAttributeMultiplier(ESM::RefId attribute) const
{
auto it = mSkillIncreases.find(attribute);
if (it == mSkillIncreases.end() || it->second == 0)
return 1;
int num = std::min(10, it->second);
// iLevelUp01Mult - iLevelUp10Mult
std::stringstream gmst;
gmst << "iLevelUp" << std::setfill('0') << std::setw(2) << num << "Mult";
return MWBase::Environment::get().getESMStore()->get<ESM::GameSetting>().find(gmst.str())->mValue.getInteger();
}The value is only capped at 10. Nothing handles values below 1, so a negative count gives iLevelUp-1Mult, iLevelUp-2Mult, and so on.
setSkillIncreasesForAttribute (npcstats.cpp:281-287) stores any non-zero integer, and the Lua binding (apps/openmw/mwlua/stats.cpp:101-111, setNpcValue) passes the value through unchanged. setSkillIncreasesForSpecialization doesn't check for negative values either.
Affected callers:
apps/openmw/mwgui/statswindow.cpp:344, inStatsWindow::onFrame, which runs every frame.apps/openmw/mwgui/levelupdialog.cpp:117,:205and:254, in the level-up dialog.
Steps to reproduce
-
Add a player-local Lua script:
local types = require('openmw.types') local self = require('openmw.self') return { engineHandlers = { onInit = function() types.Actor.stats.level(self).skillIncreasesForAttribute.strength = -2 end, }, } -
Start a new game or load a save, and open the stats window.
Expected behavior
A negative counter is treated like 0 (multiplier x1), or the API rejects or clamps negative values.
Actual behavior
GameSetting 'iLevelUp-2Mult' not found is logged every frame. Leveling up raises the same error.
Suggested fix
The smallest fix is in the getter:
if (it == mSkillIncreases.end() || it->second <= 0)
return 1;It may also be worth clamping negative values to 0, or rejecting them, in setSkillIncreasesForAttribute and setSkillIncreasesForSpecialization, or in the Lua binding. Saves that already contain a negative value would then load cleanly too.