WoW Forever Addon Pitfalls: 12 AI Mistakes and 4 Beta Traps
Models copy interface 120001 or 11503 where the wiki lists 16001, and they do math on UnitHealth, which came back as a secret number on build 69913.
Ask Our Sweaty Degenerate AI About Addon Pitfalls
Interface Numbers, Secret Health Math, WOW_PROJECT_ID, Combat Log Gaps, Beta Sound Traps & More
Anything our guides cover. Answers come from this page and the rest of our guides, with the real values charted and the guide sections linked. It's AI, so check the source before you quote it.
These are mistakes a model can make when a WoW addon prompt does not name the Forever client. Each pairs the line it may emit with the line to write instead. Porting from Retail or another client? Check each API against your target build before shipping.
- Wrong interface number
- 16001
- Secret health math
- h + 1 fails
- WOW_PROJECT_ID
- 18 (Camelot)
- Combat log
- Reported unavailable
This breakdown is part of the WoW Forever addon developer guide. To see why these mistakes happen, read WoW Forever addon patterns and the Forever API cheat sheet. You can head most of them off with the ready-to-use AI prompts.
Twelve Traps
01. Shipping Interface 120001 or 11503
Models copy Midnight guides or Classic templates. The Warcraft Wiki lists 16001 for the Forever beta. A different number can make the client you are testing flag the addon as out of date.

content.zygorguides.com/support/manual/enabling.## Interface: 120001## Interface: 1600102. Branching on WOW_PROJECT_ID
On build 1.60.1.69913, WOW_PROJECT_ID reportedly returned 1, the Mainline value. The retained October 12 probe on build 70338 instead records 18, matching Blizzard's WOW_PROJECT_CAMELOT constant. A Classic-only branch misses Forever; a catch-all branch can mistake it for another client. Compare the named constant, then check the feature's API.Source: Blizzard's Camelot project constants, retained 70338 extract inspected Oct 13, 2026; WFG probe captured Oct 12. The mirror may show a later build.
if WOW_PROJECT_ID ~= WOW_PROJECT_MAINLINE then
-- Assumes every non-Mainline client is Classic; 70338 Forever enters here.
endlocal isForever = WOW_PROJECT_CAMELOT ~= nil
and WOW_PROJECT_ID == WOW_PROJECT_CAMELOT
if isForever then
ns:UseForeverPath()
-- Only a feature that reads the preset needs this capability.
local canReadPreset = C_GameRules
and type(C_GameRules.GetForeverExperiencePreset) == "function"
if canReadPreset then
local preset = C_GameRules.GetForeverExperiencePreset()
-- Use preset for your optional preset-specific feature.
end
endThe older Warcraft Wiki example combined WOW_PROJECT_MAINLINE with LE_EXPANSION_LEVEL_CURRENT == LE_EXPANSION_CLASSIC. That first condition is false on the captured 70338 client. The revised snippet is source-checked, not tested in game; ns:UseForeverPath() represents your own addon code.
03. Adding One to UnitHealth
In a test on build 69913, type(UnitHealth("player")) prints number, yet h + 1 fails. WoW Forever Builds saw Grid2 throw "attempt to perform arithmetic on a secret number value".
local h = UnitHealth("player")
local pct = h / UnitHealthMax("player")local bar = ns.healthBar
bar:SetMinMaxValues(0, UnitHealthMax("player"))
bar:SetValue(UnitHealth("player"))This example is not tested in game; check that both setters accept the value on your build.
04. Printing a Name That Might Be Secret
Warcraft Forever reports that unit and creature names may be secret strings. It also says printing one throws an error and can blank your frame. Check first, then fall back to a value you chose.
print("Hello " .. UnitName("player"))local name = UnitName("player")
if type(issecretvalue) == "function" and issecretvalue(name) then
name = "adventurer"
end
print("Hello " .. name)05. GetSpellInfo and GetItemInfo
Both were missing on build 69913, along with GetSpellBookItemName and the old talent globals. C_Spell.GetSpellInfo returns one table. C_Item.GetItemInfo returns the same list of values as the old global.
local name, _, icon = GetSpellInfo(8690)local info = C_Spell.GetSpellInfo(8690)
if not info then
C_Spell.RequestLoadSpellData(8690)
return
end
local name, icon = info.name, info.iconID06. A Damage Meter, Politely Disguised
On Midnight, registering the combat log event throws an error. Testers report it unavailable on Forever. Blizzard said Forever includes a built-in damage meter and cooldown manager.
frame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")-- Presentation only. Let the built-in meter count.
frame:RegisterUnitEvent("UNIT_HEALTH", "player")07. Click-Cast via a Secure Snippet
Secure snippets failed to compile on build 69913. Even if a later build fixes that, Warcraft Forever lists secure attributes on Blizzard unit frames as protected, and pcall does not make the failure go away.
SecureHandlerWrapScript(button, "OnClick", button, [[
self:SetAttribute("type", "spell")
]])-- Own button, plain script, no secure attribute
-- on a Blizzard unit frame.
button:SetScript("OnClick", function()
-- open your panel, do not cast for the player
end)08. SavedVariables at File Scope
SavedVariables are nil while your file loads. The client loads saved data after your files run, and it replaces whatever your file set. A default assigned at the top is either overwritten or read too early. Players also reported the beta losing saved data between sessions until build 70009.
MyAddonDB = MyAddonDB or { enabled = true }function events:ADDON_LOADED(loaded)
if loaded ~= addonName then return end
MyAddonDB = MyAddonDB or {}
if MyAddonDB.enabled == nil then
MyAddonDB.enabled = true
end
ns.db = MyAddonDB
endSee the full lifecycle in the SavedVariables template.
09. Canceling C_Timer.After
After returns nothing. The timer object comes from NewTimer or NewTicker.
local t = C_Timer.After(5, func)
t:Cancel()local t = C_Timer.NewTimer(5, func)
t:Cancel()10. Protected Calls Hidden in Pcall
Warcraft Forever reports that ChatFrame_OpenChat, C_SuperTrack.SetSuperTrackedUserWaypoint and secure attributes on Blizzard frames fail without a Lua error. The only symptom is an interface-action counter that /reload does not reset.
pcall(C_SuperTrack.SetSuperTrackedUserWaypoint, true)local point = UiMapPoint.CreateFromCoordinates(uiMapID, x, y)
C_Map.SetUserWaypoint(point)C_Map.SetUserWaypoint places the pin; the wiki documents C_SuperTrack.SetSuperTrackedUserWaypoint as the separate call that tracks it. Warcraft Forever's page, captured September 28, lists that call as protected but names no client build, so retest on yours.
11. Faction Tests That Lie
Warcraft Forever reports that UnitIsEnemy and UnitCanAttack mean "attackable right now" on this client, not "other faction": both answer false for an unflagged enemy, in a sanctuary or on another shard. Its secret-value list names UnitCanAttack, not UnitIsEnemy, as a secret boolean. The report names no build, so retest on yours.
if UnitIsEnemy("player", unit) thenlocal them = UnitFactionGroup(unit)
local mine = UnitFactionGroup("player")
if them and mine and them ~= mine then12. Slash Commands That Never Register
The global must be SLASH_NAME1 and the SlashCmdList key must be the same NAME, spelled the same way. A local, or a key that does not match, never registers.
local SLASH_fb1 = "/fb"
SlashCmdList.fb = function() endSLASH_FOREVERBEACON1 = "/fb"
SlashCmdList["FOREVERBEACON"] = function(msg)
endFor complete safe bars, combat queues and addon compartments, see the code templates.
Four More Traps From the Beta
The twelve above cover the biggest breaks. These four are smaller. Traps 13 and 14 are unverified community beta reports from Warcraft Forever. Traps 15 and 16 come from the Warcraft Wiki's Mainline API pages, the UI family Forever runs. They have not been retested on a Forever build.
13. Playing a Sound File the Classic Way
Warcraft Forever reports that PlaySoundFile with a Sound\Interface\*.ogg path fails silently on this client. Nothing errors and nothing prints; the sound never plays.
PlaySoundFile("Sound\\Interface\\LevelUp.ogg")-- Warcraft Wiki, PlaySound: play by SoundKitID, not a file path.
PlaySound(SOUNDKIT.READY_CHECK)The wiki's PlaySound page documents playing by SoundKitID or a SOUNDKIT key. Warcraft Forever also says to check the master volume before blaming the addon.
14. Trusting a Nameplate the Instant It Appears
Warcraft Forever reports that NAME_PLATE_UNIT_ADDED fires before the unit is populated, and that plate frames carry no namePlateUnitToken on this client. Reading the unit in the same handler gets nothing useful.
frame:SetScript("OnEvent", function(self, event, unit)
self.name:SetText(UnitName(unit))
end)frame:SetScript("OnEvent", function(self, event, unit)
C_Timer.After(0, function()
self.name:SetText(UnitName(unit))
end)
end)
-- Or sweep nameplate1..nameplate40 yourself a moment later.15. Assuming a Metadata Lookup Fails Quietly
The wiki says C_AddOns.GetAddOnMetadata, unlike the old global, raises an "Invalid AddOn name" error when the addon does not exist. A model that ports the old call and keeps its nil check would stop the file on a missing optional dependency. Test the guarded pattern below on your Forever build.
local ver = C_AddOns.GetAddOnMetadata("SomeOtherAddon", "Version")
if not ver then return endlocal ok, ver = pcall(C_AddOns.GetAddOnMetadata, "SomeOtherAddon", "Version")
if not ok or not ver then return end16. Wiring the Settings Panel Through the Old Globals
The wiki dates the Settings API rewrite to patch 10.0.0, with more breaking changes in 11.0.2. Its documented pattern registers a category and opens it through Settings, not the older InterfaceOptionsFrame_OpenToCategory that Classic Era templates call.
InterfaceOptionsFrame_OpenToCategory(MyAddonOptionsPanel)local category = Settings.RegisterVerticalLayoutCategory("My Addon")
Settings.RegisterAddOnCategory(category)
-- Later, from a slash command:
Settings.OpenToCategory(category:GetID())Register the category once at load, then open it from a slash command or an addon compartment entry like the one in the Forever Beacon sample addon.
Why Models Default to These Mistakes
These examples show a risk, not a measured error rate. Without the target client named, a model asked for a health bar may reach for arithmetic, and one asked for options may call a panel API from an older interface.
The fix is context, not a cleverer prompt. Tell the model the interface number, the project ID and the APIs the beta reports, and start from the prompt templates for Forever addons.
Established addons are adapting the same way, by testing on the beta. RestedXP's free guide addon has shipped Forever route fixes in its GitHub releases through September 2026, and Zygor Guides says its Forever guides reach Elite subscribers at launch.

Verifying a Fix Before You Ship It
None of these sixteen fixes is guaranteed to survive the next beta build. Retest each one on the build you are running.
Start with /run print(select(2, GetBuildInfo()), select(4, GetBuildInfo())), which prints the build and the interface number. Then run WoW Forever Builds' health test from trap 03: /run local h = UnitHealth("player"); print(type(h), pcall(function() return h + 1 end)). On build 69913 it printed number false: pcall caught an error, so the addition was refused. If it prints true, that read is no longer secret on your build. That result covers only this test; test the status bar example separately.
For trap 08, log out fully and back in, not just /reload, and check that your saved table survived. Players reported a SavedVariables restore bug from Sep 21, 2026, and one player said build 70009 fixed it on Sep 25. Blizzard hasn't confirmed a fix.
Test trap 11 against an unflagged enemy player, in a sanctuary or on another shard. Warcraft Forever reports that UnitIsEnemy and UnitCanAttack both return false there.
For the protected calls in traps 07 and 10, watch the AddOns panel's interface-action counter rather than pcall's return value. /reload does not reset that counter, so restart the client before you retest, or an old count will make a working fix look broken.
Note the build number next to any fix you rely on, the way the API cheat sheet marks rows observed on build 69913. A trap fixed on one build can reopen on the next.
Key Facts
- Wrong interface number ChangedModels copy 120001 or 11503; the wiki lists 16001 for the Forever beta
- Secret health math Changedtype() says number, but h + 1 fails; pcall returns false instead of a sum
- WOW_PROJECT_ID Changed18 (WOW_PROJECT_CAMELOT) in the October 12 WFG probe on build 70338; older build 69913 reported 1Classic: Classic Era returns 2 (WOW_PROJECT_CLASSIC).
- Combat log RemovedRegistering COMBAT_LOG_EVENT_UNFILTERED errors on Midnight; reported unavailable on Forever
Sources
- What the WoW Forever beta breaks for addons: secret health values, dead secure snippets, new APIsWoW Forever Builds
- AddonsWarcraft Forever
- TOC formatWarcraft Wiki
- Secret ValuesWarcraft Wiki
- Patch 12.0.0/API changesWarcraft Wiki
- C_Item.GetItemInfoWarcraft Wiki
- Saving variables between game sessionsWarcraft Wiki
- WOWF Beta: Addon SavedVariables appear to write correctly to disk but are not restored at startupWorld of Warcraft Forums (player bug report)
- C_Map.SetUserWaypointWarcraft Wiki
- C_AddOns.GetAddOnMetadataWarcraft Wiki
- Settings APIWarcraft Wiki
- PlaySoundWarcraft Wiki
- RXPGuides releasesRestedXP (GitHub)
- Zygor's World of Warcraft Forever guides launching this NovemberZygor Guides
- Blizzard client source: ProjectConstants.lua (retained build 70338; mirror may change)Blizzard Entertainment (source mirrored by Gethe)
- Zygor manual: enabling
