English
Troubleshooting
UpdateEsoComputedStatsList_Real não está disponível / engine not initialized
calculateBuild() was called before initEsoEngineFromData(), or the init call failed silently.
ts
// once, before ANY calculation
initEsoEngineFromData({ initData });The init is a singleton — calling it again is a no-op, so it is safe to call at every request boundary if you want.
Vendor files not found at runtime (Next.js / serverless)
The engine scripts are loaded at runtime via fs.readFileSync from the package's vendor/ folder. Bundlers and serverless tracers cannot see those dynamic reads — in Next.js you must include them explicitly:
ts
// next.config.ts
const nextConfig: NextConfig = {
serverExternalPackages: ['uesp-eso-build-wrapper'],
outputFileTracingIncludes: {
'/**': ['./node_modules/uesp-eso-build-wrapper/vendor/**'],
},
};Without this, the engine throws at runtime in Vercel/AWS Lambda even though it works locally.
A stat value looks wrong
Do not add math to your code to "fix" it. All formulas live in the vendored UESP engine; the wrapper only injects inputs. A wrong value almost always means wrong input data:
- Run debugBuild() with the same input and inspect
inputValues— which category contributed the unexpected value? - Check names/spellings: buffs, toggles, races and mundus stones are matched exactly; a typo silently does nothing.
- Check the game data version (
_metainuesp-game-data.json) — old data means old formulas. - Compare against the UESP Build Editor with the same build. If the editor differs, open an issue with your input.
CP nodes are not applying
character.championPointsmust be > 0 — nodes are ignored when the total is 0.- The node must be unlocked:
isUnlockeddefaults totrue, but explicitfalseexcludes it. - On the legacy path,
currentBonusmust be a number or a"N%"string.
A toggle skill does nothing
- Toggle skills with
requiresCyrodiil: trueonly apply whencharacter.cyrodiil: trueis set. - Toggle skills with
isPassive: trueneed the backing skill unlocked viapassiveSkillsor present on a skill bar. - Names must match listAvailableToggleSkills() exactly.
Race/class name not recognized
The engine matches names as they appear in the UESP Build Editor ("High Elf", not "Altmer"; "Dragonknight", not "DK"). Unknown names behave as "none selected". Use listRacialPassives() as a sanity check — an empty result means the name doesn't match the catalog.
Concurrency / multiple calculations
initEsoEngineFromData() loads the engine once per process — every calculateBuild() afterwards is stateless (inputs are fully reset between calls). You do not need locks or per-request init; a single global init at startup is the intended pattern.
For test suites, run tests in a single process/fork — the vendored engine writes to Node globals and is not safe for parallel workers.