OpenRA/OpenRA · error · YamlException

Error parsing GameSpeed {node.Key}: {label}: {e.Missing.Join

Error message

Error parsing GameSpeed {node.Key}: {label}: {e.Missing.JoinWith(", ")}

What it means

Thrown by GameSpeed.LoadSpeeds when FieldLoader.Load<GameSpeed> for an individual speed entry raises MissingFieldsException because a [FieldLoader.Require] field (e.g. Timestep) is absent. The message names the speed key and lists the missing required properties.

Source

Thrown at OpenRA.Game/GameSpeed.cs:55

		public readonly Dictionary<string, GameSpeed> Speeds;

		static object LoadSpeeds(MiniYaml y)
		{
			var ret = new Dictionary<string, GameSpeed>();
			var speedsNode = y.NodeWithKeyOrDefault("Speeds");
			if (speedsNode == null)
				throw new YamlException("Error parsing GameSpeeds: Missing Speeds node!");

			foreach (var node in speedsNode.Value.Nodes)
			{
				try
				{
					ret.Add(node.Key, FieldLoader.Load<GameSpeed>(node.Value));
				}
				catch (FieldLoader.MissingFieldsException e)
				{
					var label = e.Missing.Length > 1 ? "Required properties missing" : "Required property missing";
					throw new YamlException($"Error parsing GameSpeed {node.Key}: {label}: {e.Missing.JoinWith(", ")}");
				}
			}

			return ret;
		}
	}
}

View on GitHub (pinned to a520984d91)

Solutions

  1. Add the listed missing required field(s) to the named speed entry under Speeds.
  2. Check the GameSpeed class for the exact required field names and types.
  3. After a SDK upgrade, lint mod.yaml to surface newly-required speed fields.
  4. Copy a complete speed entry from a reference mod and adjust values.

Example fix

# mod.yaml - before
Speeds:
    default:
        DefaultSpeed: default
# after - add required Timestep
Speeds:
    default:
        Timestep: 40
        DefaultSpeed: default
Defensive patterns

Strategy: validation

Validate before calling

// Validate each speed entry has required GameSpeed fields before loading
var required = typeof(GameSpeed).GetFields()
    .Where(f => f.GetCustomAttribute<FieldLoader.RequireAttribute>() != null)
    .Select(f => f.Name);
var present = node.Value.Nodes.Select(n => n.Key).ToHashSet();
var missing = required.Where(r => !present.Contains(r)).ToList();
if (missing.Count > 0) // report missing fields before FieldLoader.Load

Try / catch

try { /* load Speeds */ }
catch (YamlException ex) when (ex.Message.Contains("Error parsing GameSpeed"))
{ /* add the listed missing fields to the named speed entry */ }

Prevention

When it happens

Trigger: Loading a Speeds child node whose GameSpeed mapping omits a required field, so FieldLoader.Load throws MissingFieldsException that is re-wrapped with the node key and missing field list.

Common situations: A speed entry missing Timestep or another required field after a SDK change added a new mandatory field; incomplete copy of a speed definition; a renamed field whose old key remains.

Related errors


AI-assisted analysis of OpenRA/OpenRA@a520984d91 (2026-08-13). Data as JSON: /api/errors/9285abbb4c9d2d8b. Report an issue: GitHub.