{"record":{"id":"c793a6655c5291e8","repo":"OpenRA/OpenRA","slug":"weapon-weapontolower-has-an-invalid-number-of","errorCode":null,"errorMessage":"Weapon '{weaponToLower}' has an invalid number of BurstDelays, must be single entry or Burst - 1.","messagePattern":"Weapon '(.+?)' has an invalid number of BurstDelays, must be single entry or Burst - 1\\.","errorType":"validation","errorClass":"YamlException","httpStatus":null,"severity":"error","filePath":"OpenRA.Mods.Common/Traits/Armament.cs","lineNumber":104,"sourceCode":"\n\t\t[Desc(\"Ammo the weapon consumes per shot.\")]\n\t\tpublic readonly int AmmoUsage = 1;\n\n\t\tpublic override object Create(ActorInitializer init) { return new Armament(init.Self, this); }\n\n\t\tpublic override void RulesetLoaded(Ruleset rules, ActorInfo ai)\n\t\t{\n\t\t\tvar weaponToLower = Weapon.ToLowerInvariant();\n\t\t\tif (!rules.Weapons.TryGetValue(weaponToLower, out var weaponInfo))\n\t\t\t\tthrow new YamlException($\"Weapons Ruleset does not contain an entry '{weaponToLower}'\");\n\n\t\t\tWeaponInfo = weaponInfo;\n\t\t\tModifiedRange = new WDist(Util.ApplyPercentageModifiers(\n\t\t\t\tWeaponInfo.Range.Length,\n\t\t\t\tai.TraitInfos<IRangeModifierInfo>().Select(m => m.GetRangeModifierDefault())));\n\n\t\t\tif (WeaponInfo.Burst > 1 && WeaponInfo.BurstDelays.Length > 1 && (WeaponInfo.BurstDelays.Length != WeaponInfo.Burst - 1))\n\t\t\t\tthrow new YamlException($\"Weapon '{weaponToLower}' has an invalid number of BurstDelays, must be single entry or Burst - 1.\");\n\n\t\t\tif (WeaponInfo.ReloadDelay <= 0)\n\t\t\t\tthrow new YamlException($\"Weapon '{weaponToLower}' ReloadDelay value must not be equal to or lower than 0\");\n\n\t\t\tbase.RulesetLoaded(rules, ai);\n\t\t}\n\t}\n\n\tpublic class Armament : PausableConditionalTrait<ArmamentInfo>, ITick\n\t{\n\t\tpublic readonly WeaponInfo Weapon;\n\t\tpublic readonly Barrel[] Barrels;\n\t\tTurreted turret;\n\t\tHovers hovers;\n\n\t\tBodyOrientation coords;\n\t\tINotifyBurstComplete[] notifyBurstComplete;\n\t\tList<(Actor NotifyActor, INotifyAttack Notify)> notifyAttacks;","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/OpenRA/OpenRA/blob/a520984d91eda9de48a62b1d15c1e3bad0d4fb1a/OpenRA.Mods.Common/Traits/Armament.cs#L86-L122","documentation":"Thrown by ArmamentInfo.RulesetLoaded when a multi-shot weapon defines a BurstDelays list whose length is neither 1 (single shared delay) nor Burst-1 (one delay between each pair of shots). The engine needs exactly one delay per inter-shot gap, so any other count is invalid and a YamlException is raised.","triggerScenarios":"A weapon with Burst>1 and a BurstDelays list whose length is >1 and != Burst-1 (e.g. Burst=4 but BurstDelays has 2 or 4 entries). The check only applies when Burst>1 and BurstDelays.Length>1.","commonSituations":"Editing Burst without updating BurstDelays; copy-pasting delays from a weapon with a different Burst count; misunderstanding that BurstDelays of length Burst-1 covers gaps between consecutive shots.","solutions":["Set BurstDelays to a single value (applies to every gap) OR exactly Burst-1 entries.","Recount BurstDelays entries to equal Burst-1 when providing per-gap delays.","When changing Burst, immediately re-derive the BurstDelays list length."],"exampleFix":"# before (invalid: Burst 4, 2 delays)\nWeapon: baz\nBurst: 4\nBurstDelays: 20, 40\n\n# after (per-gap: Burst-1 = 3 delays)\nWeapon: baz\nBurst: 4\nBurstDelays: 20, 40, 20","handlingStrategy":"validation","validationCode":"// Validate BurstDelays length against Burst\nif (burst > 1 && burstDelays.Length > 1 && burstDelays.Length != burst - 1)\n    throw new YamlException($\"BurstDelays length {burstDelays.Length} must be 1 or Burst-1={burst - 1}.\");","typeGuard":"bool ValidBurstDelays(int burst, int delays) =>\n    burst <= 1 || delays <= 1 || delays == burst - 1;","tryCatchPattern":null,"preventionTips":["When Burst>1, use either one shared BurstDelays value or exactly Burst-1 values.","Re-derive BurstDelays whenever Burst changes.","Lint weapon YAML for the Burst/BurstDelays invariant."],"tags":["weapon","yaml","ruleset","config","balance"],"backgroundTag":null,"analyzedSha":"a520984d91eda9de48a62b1d15c1e3bad0d4fb1a","analyzedAt":"2026-08-13T15:30:14.787Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}