{"record":{"id":"b98ff72b157390e7","repo":"OpenRA/OpenRA","slug":"withaimanimation-needs-exactly-one-sprite-body-wit","errorCode":null,"errorMessage":"WithAimAnimation needs exactly one sprite body with matching name.","messagePattern":"WithAimAnimation needs exactly one sprite body with matching name\\.","errorType":"validation","errorClass":"YamlException","httpStatus":null,"severity":"error","filePath":"OpenRA.Mods.Common/Traits/Render/WithAimAnimation.cs","lineNumber":36,"sourceCode":"\t{\n\t\t[Desc(\"Armament name\")]\n\t\tpublic readonly string Armament = \"primary\";\n\n\t\t[SequenceReference]\n\t\t[FieldLoader.Require]\n\t\t[Desc(\"Displayed while targeting.\")]\n\t\tpublic readonly string Sequence = null;\n\n\t\t[Desc(\"Which sprite body to modify.\")]\n\t\tpublic readonly string Body = \"body\";\n\n\t\tpublic override object Create(ActorInitializer init) { return new WithAimAnimation(init, this); }\n\n\t\tpublic override void RulesetLoaded(Ruleset rules, ActorInfo ai)\n\t\t{\n\t\t\tvar match = ai.TraitInfos<WithSpriteBodyInfo>().SingleOrDefault(w => w.Name == Body);\n\t\t\tif (match == null)\n\t\t\t\tthrow new YamlException(\"WithAimAnimation needs exactly one sprite body with matching name.\");\n\n\t\t\tbase.RulesetLoaded(rules, ai);\n\t\t}\n\t}\n\n\tpublic class WithAimAnimation : ConditionalTrait<WithAimAnimationInfo>, INotifyAiming\n\t{\n\t\treadonly AttackBase[] attackBases;\n\t\treadonly WithSpriteBody wsb;\n\n\t\tpublic WithAimAnimation(ActorInitializer init, WithAimAnimationInfo info)\n\t\t\t: base(info)\n\t\t{\n\t\t\tattackBases = init.Self.TraitsImplementing<AttackBase>().ToArray();\n\t\t\twsb = init.Self.TraitsImplementing<WithSpriteBody>().First(w => w.Info.Name == Info.Body);\n\t\t}\n\n\t\tvoid UpdateSequence(bool isAiming)","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/OpenRA/OpenRA/blob/a520984d91eda9de48a62b1d15c1e3bad0d4fb1a/OpenRA.Mods.Common/Traits/Render/WithAimAnimation.cs#L18-L54","documentation":"Thrown in WithAimAnimationInfo.RulesetLoaded when SingleOrDefault finds zero WithSpriteBodyInfo traits with a Name matching the Body field. WithAimAnimation switches a sprite body to an aiming sequence when the actor is targeting, so it needs exactly one WithSpriteBody to control. Note: SingleOrDefault throws InvalidOperationException if there are multiple matches, but this YamlException is thrown only for the zero-match case.","triggerScenarios":"An actor has a WithAimAnimation trait with Body set to a name (default 'body'), but no WithSpriteBody trait exists on the actor with that name. This can happen if WithSpriteBody was removed or renamed, or the Body field references a non-existent body.","commonSituations":"Renaming a WithSpriteBody's Name without updating WithAimAnimation.Body; removing WithSpriteBody while leaving WithAimAnimation; adding WithAimAnimation to an actor that uses a different body trait (e.g. WithEmbeddedBodyPalette but no sprite body); typo in the Body field.","solutions":["Ensure the actor has exactly one WithSpriteBody trait whose Name matches the Body field on WithAimAnimation (default 'body' for both).","If the Body field is customized, verify the matching WithSpriteBody Name is spelled identically.","If the actor has no sprite body, remove the WithAimAnimation trait."],"exampleFix":"// before (no matching WithSpriteBody)\nWithAimAnimation:\n  Body: torso\nWithSpriteBody:\n  Name: body\n\n// after (names match)\nWithAimAnimation:\n  Body: body\nWithSpriteBody:\n  Name: body","handlingStrategy":"validation","validationCode":"// Verify exactly one WithSpriteBody matches the Body field\nvar spriteBodies = actorInfo.TraitInfos<WithSpriteBodyInfo>();\nforeach (var waa in actorInfo.TraitInfos<WithAimAnimationInfo>())\n{\n    var match = spriteBodies.SingleOrDefault(w => w.Name == waa.Body);\n    if (match == null)\n        Log.Error($\"WithAimAnimation on {actorName}: no WithSpriteBody with Name '{waa.Body}'.\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep WithSpriteBody Name and WithAimAnimation Body in sync; both default to 'body'.","When renaming a sprite body, search for all referencing traits.","Use the default 'body' name unless multiple sprite bodies are needed."],"tags":["openra","yaml-config","render","animation","trait-dependency"],"backgroundTag":null,"analyzedSha":"a520984d91eda9de48a62b1d15c1e3bad0d4fb1a","analyzedAt":"2026-08-13T15:30:14.787Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}