Description
Importing a character whose main/displayed skill is a minion skill (e.g. Summon Infernal Hound) via Character Import crashes Path of Building once the passive tree is brought in. The error is a nil access in RefreshSkillSelectControls.
Error
In 'OnFrame': Modules/Build.lua:2044: bad argument #1 to 'ipairs' (table expected, got nil)
stack traceback:
[C]: in function 'ipairs'
Modules/Build.lua:2044: in function 'RefreshSkillSelectControls'
Modules/Build.lua:1344: in function 'CallMode'
Modules/Main.lua:372: in function <Modules/Main.lua:342>
[C]: in function 'PCall'
Launch.lua:112: in function 'OnFrame'
Steps to reproduce
The key condition is that the currently displayed main skill is a minion-summon (e.g. Summon Infernal Hound) at the moment a passive tree is imported.
- Have a build whose main displayed skill is a minion-summon (Summon Infernal Hound / a Skeletal minion). Easiest: import a minion character's Items & Skills, then set that minion summon as the main skill (or open an existing minion build).
- Import/Export Build → Character Import → Passive Tree and Jewels (or otherwise import/replace the passive tree).
- On the next frame,
RefreshSkillSelectControls runs for the minion main skill before the minion's activeSkillList has been rebuilt → crash.
Notes from investigation:
- It does not crash when the displayed main skill is a non-summon (an attack/spell skill, or a trigger like Cast on Minion Death) — the crashing branch (
if activeSkill.minion then) only runs for skills that summon a minion.
- A fresh character import sometimes auto-selects a non-summon group as the main skill, in which case it won't crash; it reliably crashes when the minion-summon is the displayed main skill during the tree import.
Workaround for users: import the Passive Tree first (before any minion-summon is the main skill), then Items and Skills.
Root cause
Modules/Build.lua, RefreshSkillSelectControls:
2043 if activeSkill.minion then
2044 for _, minionSkill in ipairs(activeSkill.minion.activeSkillList) do
...
2051 for _, statSet in ipairs(activeSkill.minion.activeSkillList[controls.mainSkillMinionSkill.selIndex]...) do
The code guards on activeSkill.minion being truthy, but then assumes activeSkill.minion.activeSkillList is a table. During the import transition the minion object exists but its activeSkillList has not yet been (re)built by a calculation pass, so it is nil when RefreshSkillSelectControls runs on the next frame — ipairs(nil) throws.
Suggested fix
Guard the inner access (both line 2044 and the dependent line 2051):
if activeSkill.minion and activeSkill.minion.activeSkillList then
for _, minionSkill in ipairs(activeSkill.minion.activeSkillList) do
...
end
i.e. fall through to the else "" branch when the minion's skill list isn't ready, rather than dereferencing it.
Version
Reproduced on the latest dev (commit a82a33b), reported PoB version 0.20.0. Confirmed the unguarded access is still present in current dev.
Description
Importing a character whose main/displayed skill is a minion skill (e.g. Summon Infernal Hound) via Character Import crashes Path of Building once the passive tree is brought in. The error is a
nilaccess inRefreshSkillSelectControls.Error
Steps to reproduce
The key condition is that the currently displayed main skill is a minion-summon (e.g. Summon Infernal Hound) at the moment a passive tree is imported.
RefreshSkillSelectControlsruns for the minion main skill before the minion'sactiveSkillListhas been rebuilt → crash.Notes from investigation:
if activeSkill.minion then) only runs for skills that summon a minion.Workaround for users: import the Passive Tree first (before any minion-summon is the main skill), then Items and Skills.
Root cause
Modules/Build.lua,RefreshSkillSelectControls:The code guards on
activeSkill.minionbeing truthy, but then assumesactiveSkill.minion.activeSkillListis a table. During the import transition the minion object exists but itsactiveSkillListhas not yet been (re)built by a calculation pass, so it isnilwhenRefreshSkillSelectControlsruns on the next frame —ipairs(nil)throws.Suggested fix
Guard the inner access (both line 2044 and the dependent line 2051):
i.e. fall through to the
else"" branch when the minion's skill list isn't ready, rather than dereferencing it.Version
Reproduced on the latest
dev(commit a82a33b), reported PoB version 0.20.0. Confirmed the unguarded access is still present in currentdev.