{"record":{"id":"276601d11331007a","repo":"OpenRA/OpenRA","slug":"weapons-ruleset-does-not-contain-an-entry-weapon-276601","errorCode":null,"errorMessage":"Weapons Ruleset does not contain an entry '{weaponToLower}'","messagePattern":"Weapons Ruleset does not contain an entry '(.+?)'","errorType":"validation","errorClass":"YamlException","httpStatus":null,"severity":"error","filePath":"OpenRA.Mods.Common/Traits/Armament.cs","lineNumber":96,"sourceCode":"\t\t[CursorReference]\n\t\t[Desc(\"Cursor to display when hovering over a valid target.\")]\n\t\tpublic readonly string Cursor = \"attack\";\n\n\t\t// TODO: same as above\n\t\t[CursorReference]\n\t\t[Desc(\"Cursor to display when hovering over a valid target that is outside of range.\")]\n\t\tpublic readonly string OutsideRangeCursor = \"attackoutsiderange\";\n\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{","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/OpenRA/OpenRA/blob/a520984d91eda9de48a62b1d15c1e3bad0d4fb1a/OpenRA.Mods.Common/Traits/Armament.cs#L78-L114","documentation":"Thrown by ArmamentInfo.RulesetLoaded when the Armament's Weapon name (lowercased) is absent from the ruleset Weapons table. Every armament must resolve to a WeaponInfo at load time; a missing weapon aborts ruleset assembly with a YamlException.","triggerScenarios":"An actor's Armament trait declares a Weapon that is not defined in weapons.yaml, or is defined in a mod not loaded. Raised during RulesetLoaded for the actor.","commonSituations":"Typo in the Weapon field; referencing a weapon removed in a mod update; case mismatch; weapon defined under a different mod/parent; copy-pasting an actor without copying its weapon.","solutions":["Confirm the Weapon value matches (case-insensitively) an existing weapons.yaml entry.","Add the missing weapon definition to weapons.yaml.","Correct typos/whitespace in the Weapon field.","If migrating mods, port the required weapon definitions alongside the actor."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Validate armament weapon exists at load time\nvar key = weapon.ToLowerInvariant();\nif (!rules.Weapons.ContainsKey(key))\n    throw new YamlException($\"Armament weapon '{key}' not found in ruleset.\");","typeGuard":"bool WeaponExists(Ruleset rules, string name) => rules.Weapons.ContainsKey(name.ToLowerInvariant());","tryCatchPattern":null,"preventionTips":["Ensure every Armament Weapon matches a weapons.yaml entry.","Run a ruleset validator that resolves all weapon references.","Port weapon definitions when migrating actors between mods."],"tags":["weapon","trait","yaml","ruleset","config"],"backgroundTag":null,"analyzedSha":"a520984d91eda9de48a62b1d15c1e3bad0d4fb1a","analyzedAt":"2026-08-13T15:30:14.787Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}