Bug Report: Multiple crashes and compatibility issues with AzerothCore 3.3.5a (Playerbot branch)
Environment
Core: AzerothCore WotLK 3.3.5a (Playerbot branch from mod-playerbots/azerothcore-wotlk)
OS: Ubuntu 24.04 LTS
Module: mod-dungeon-master (InstanceForge)
Config: ~500 PlayerBots active, MaxPlayerLevel=60 (Classic phase), solo/small group play
Summary
After extensive testing over the past week, we identified and fixed 15 issues in DungeonMasterMgr.cpp — ranging from SQL syntax incompatibilities to a server segfault (use-after-free) and client crashes (Error #132). Below is the full list with diagnosis and fix for each.
- SQL syntax: id1 → id
Symptom: Silent SQL failures — creatures not spawning.
Cause: Creature spawn queries used id1 (TrinityCore syntax). AzerothCore uses id.
Fix: Replace id1 with id in all creature spawn SQL queries.
- SQLTransaction → auto trans
Symptom: Compilation error.
Cause: SQLTransaction is deprecated in AzerothCore.
Fix: Replace SQLTransaction trans = ... with auto trans = ....
- Missing INNER JOIN creature_template_model
Symptom: Creatures spawning without valid display models, causing visual glitches.
Cause: Trash query (~line 295) and boss query (~line 395) did not join creature_template_model, so creatures without a valid DisplayID could be selected.
Fix: Add INNER JOIN creature_template_model ctm ON ctm.CreatureID = ct.entry to both queries.
- Missing unit_flags filter
Symptom: Quest NPCs, immune-to-PC, and immune-to-NPC creatures spawning as dungeon mobs.
Cause: No filter on unit_flags.
Fix: Add AND NOT (ct.unit_flags & 33538) to both trash and boss spawn queries. Bitmask 33538 covers quest NPCs, immune-to-PC, and immune-to-NPC flags.
- Missing flags_extra filter
Symptom: Creatures with problematic extra flags spawning.
Cause: No filter on flags_extra.
Fix: Add AND NOT (ct.flags_extra & 128) to both queries.
- Creature level cap for Classic phase
Symptom: Level 70-80 creatures spawning in a level-60 capped server.
Cause: No max level filter in creature selection queries.
Fix: Add AND ct.maxlevel <= 63 to both queries (adjustable per content phase).
- Invisible/trigger creatures spawning
Symptom: Mobs visible on minimap but invisible and untargetable in-game.
Cause: Certain creature entries are triggers, invisible models, or have broken pathfinding (e.g., Skeletal Raider entry 1110).
Fix: Add AND ct.entry NOT IN (1110,2673,2674,22507,27664,27697,28301,40281) to both queries.
- Client crash Error #132 — Invalid DisplayIDs
Symptom: WoW client crashes with Error #132 when entering a Dungeon Master instance.
Cause: Certain CreatureDisplayID values in creature_template_model reference CreatureDisplayInfoExtra records with an empty BakeName field. The client cannot render these and crashes. Confirmed via wowdev.wiki — address 0x0082C7C9 in CreatureDisplayInfoExtra.
Fix: Add a NOT IN subquery to both trash and boss spawn queries:
sqlAND ct.entry NOT IN (
SELECT ctm2.CreatureID FROM creature_template_model ctm2
WHERE ctm2.CreatureDisplayID IN (15331,15332,15444,17116,20392,21951,23290,23296,23836,23886,29323)
)
- Server crash (SEGFAULT) — Use-after-free in Update()
Symptom: Server segfaults shortly after dungeon instances are created.
GDB backtrace:
#0 Object::IsInWorld() at Object.h:109 — this=0x1 (INVALID pointer)
#1 DungeonMasterMgr::Update() at DungeonMasterMgr.cpp:3452
stray = 0x1 (corrupted pointer, object already destroyed)
npcEntry = 500000
Cause: The "Sweep for stray creatures" block in Update() iterates over InstanceMap::GetCreatureBySpawnIdStore(), which is an unordered_multimap<uint32, Creature*>. Some Creature* pointers in this map become dangling (value 0x1) after the core destroys the creature objects. The code calls stray->IsInWorld() on these invalid pointers, causing a use-after-free segfault.
Fix: Disabled the entire "stray sweep" block (~lines 3443-3463) by commenting it out. This block's purpose was to despawn non-DM creatures that wandered into the instance — it is not critical for dungeon functionality. A proper fix would require the core to notify the module when creatures are despawned, or using GUID-based lookups via ObjectAccessor instead of raw pointers.
- Additional pointer safety guards
Symptom: Potential crashes in other code paths using the same CreatureBySpawnIdStore.
Fix: Added reinterpret_cast<uintptr_t> guards to filter out obviously invalid pointers (address < 0x10000) before dereferencing:
Creature* c in Phase 2 despawn (~line 1008): if (!c || reinterpret_cast<uintptr_t>(c) < 0x10000) continue;
GameObject* go (~line 1066): Added reinterpret_cast<uintptr_t>(go) < 0x10000 to existing null check.
- Boss query column index out of bounds
Symptom: Server crash or incorrect boss spawn positions.
Cause: In GetSpawnPointsForMap (~line 917), the boss query returned 6 columns but the code read index f[6] (0-based), which is out of bounds.
Fix: Changed f[6] to f[5].
- LoadRewardItems quality cap
Symptom: Epic and legendary items not appearing as dungeon rewards.
Cause: LoadRewardItems filtered items to Quality ≤ 4 (Rare max).
Fix: Changed filter to Quality ≤ 5 to include Epic items.
13-14. Custom reward functions (enhancement, not bugfix)
Added PickT3ForClass() (Master tier ≥5 guarantees class-specific T3 set pieces) and PickLegendary() (Roguelike tier ≥7 can drop Sulfuras 17182, Thunderfury 19019, Ashbringer 13262, Atiesh variants 22589/22630/22631/22632).
Recommendation
The most critical issue is #9 (use-after-free). The CreatureBySpawnIdStore can contain dangling pointers after the core destroys creatures. Any code iterating over this store with raw Creature* pointers is unsafe. The recommended long-term fix is either:
Register a creature death/despawn hook to remove entries from any module-side tracking structures, or
Use ObjectGuid + ObjectAccessor::GetCreature() for lookups instead of caching raw pointers.
Issues #1-2 are straightforward AzerothCore vs TrinityCore compatibility fixes that could be resolved upstream.
Issues #3-8 are query hardening that would benefit all users running the module on AzerothCore.
Bug Report: Multiple crashes and compatibility issues with AzerothCore 3.3.5a (Playerbot branch)
Environment
Core: AzerothCore WotLK 3.3.5a (Playerbot branch from mod-playerbots/azerothcore-wotlk)
OS: Ubuntu 24.04 LTS
Module: mod-dungeon-master (InstanceForge)
Config: ~500 PlayerBots active, MaxPlayerLevel=60 (Classic phase), solo/small group play
Summary
After extensive testing over the past week, we identified and fixed 15 issues in DungeonMasterMgr.cpp — ranging from SQL syntax incompatibilities to a server segfault (use-after-free) and client crashes (Error #132). Below is the full list with diagnosis and fix for each.
Symptom: Silent SQL failures — creatures not spawning.
Cause: Creature spawn queries used id1 (TrinityCore syntax). AzerothCore uses id.
Fix: Replace id1 with id in all creature spawn SQL queries.
Symptom: Compilation error.
Cause: SQLTransaction is deprecated in AzerothCore.
Fix: Replace SQLTransaction trans = ... with auto trans = ....
Symptom: Creatures spawning without valid display models, causing visual glitches.
Cause: Trash query (~line 295) and boss query (~line 395) did not join creature_template_model, so creatures without a valid DisplayID could be selected.
Fix: Add INNER JOIN creature_template_model ctm ON ctm.CreatureID = ct.entry to both queries.
Symptom: Quest NPCs, immune-to-PC, and immune-to-NPC creatures spawning as dungeon mobs.
Cause: No filter on unit_flags.
Fix: Add AND NOT (ct.unit_flags & 33538) to both trash and boss spawn queries. Bitmask 33538 covers quest NPCs, immune-to-PC, and immune-to-NPC flags.
Symptom: Creatures with problematic extra flags spawning.
Cause: No filter on flags_extra.
Fix: Add AND NOT (ct.flags_extra & 128) to both queries.
Symptom: Level 70-80 creatures spawning in a level-60 capped server.
Cause: No max level filter in creature selection queries.
Fix: Add AND ct.maxlevel <= 63 to both queries (adjustable per content phase).
Symptom: Mobs visible on minimap but invisible and untargetable in-game.
Cause: Certain creature entries are triggers, invisible models, or have broken pathfinding (e.g., Skeletal Raider entry 1110).
Fix: Add AND ct.entry NOT IN (1110,2673,2674,22507,27664,27697,28301,40281) to both queries.
Symptom: WoW client crashes with Error #132 when entering a Dungeon Master instance.
Cause: Certain CreatureDisplayID values in creature_template_model reference CreatureDisplayInfoExtra records with an empty BakeName field. The client cannot render these and crashes. Confirmed via wowdev.wiki — address 0x0082C7C9 in CreatureDisplayInfoExtra.
Fix: Add a NOT IN subquery to both trash and boss spawn queries:
sqlAND ct.entry NOT IN (
SELECT ctm2.CreatureID FROM creature_template_model ctm2
WHERE ctm2.CreatureDisplayID IN (15331,15332,15444,17116,20392,21951,23290,23296,23836,23886,29323)
)
Symptom: Server segfaults shortly after dungeon instances are created.
GDB backtrace:
#0 Object::IsInWorld() at Object.h:109 — this=0x1 (INVALID pointer)
#1 DungeonMasterMgr::Update() at DungeonMasterMgr.cpp:3452
stray = 0x1 (corrupted pointer, object already destroyed)
npcEntry = 500000
Cause: The "Sweep for stray creatures" block in Update() iterates over InstanceMap::GetCreatureBySpawnIdStore(), which is an unordered_multimap<uint32, Creature*>. Some Creature* pointers in this map become dangling (value 0x1) after the core destroys the creature objects. The code calls stray->IsInWorld() on these invalid pointers, causing a use-after-free segfault.
Fix: Disabled the entire "stray sweep" block (~lines 3443-3463) by commenting it out. This block's purpose was to despawn non-DM creatures that wandered into the instance — it is not critical for dungeon functionality. A proper fix would require the core to notify the module when creatures are despawned, or using GUID-based lookups via ObjectAccessor instead of raw pointers.
Symptom: Potential crashes in other code paths using the same CreatureBySpawnIdStore.
Fix: Added reinterpret_cast<uintptr_t> guards to filter out obviously invalid pointers (address < 0x10000) before dereferencing:
Creature* c in Phase 2 despawn (~line 1008): if (!c || reinterpret_cast<uintptr_t>(c) < 0x10000) continue;
GameObject* go (~line 1066): Added reinterpret_cast<uintptr_t>(go) < 0x10000 to existing null check.
Symptom: Server crash or incorrect boss spawn positions.
Cause: In GetSpawnPointsForMap (~line 917), the boss query returned 6 columns but the code read index f[6] (0-based), which is out of bounds.
Fix: Changed f[6] to f[5].
Symptom: Epic and legendary items not appearing as dungeon rewards.
Cause: LoadRewardItems filtered items to Quality ≤ 4 (Rare max).
Fix: Changed filter to Quality ≤ 5 to include Epic items.
13-14. Custom reward functions (enhancement, not bugfix)
Added PickT3ForClass() (Master tier ≥5 guarantees class-specific T3 set pieces) and PickLegendary() (Roguelike tier ≥7 can drop Sulfuras 17182, Thunderfury 19019, Ashbringer 13262, Atiesh variants 22589/22630/22631/22632).
Recommendation
The most critical issue is #9 (use-after-free). The CreatureBySpawnIdStore can contain dangling pointers after the core destroys creatures. Any code iterating over this store with raw Creature* pointers is unsafe. The recommended long-term fix is either:
Register a creature death/despawn hook to remove entries from any module-side tracking structures, or
Use ObjectGuid + ObjectAccessor::GetCreature() for lookups instead of caching raw pointers.
Issues #1-2 are straightforward AzerothCore vs TrinityCore compatibility fixes that could be resolved upstream.
Issues #3-8 are query hardening that would benefit all users running the module on AzerothCore.