OpenRA/OpenRA · error · YamlException

Cursor {kv.Value.Name}: Start is greater than the length of

Error message

Cursor {kv.Value.Name}: Start is greater than the length of the sprite sequence.

What it means

Thrown by CursorManager while building hardware/software cursors from the mod's cursor YAML. The CursorSequence's 'Start' field names a zero-based offset into the sprite file, and the engine verifies Start does not exceed the number of frames the loader actually returned (cursorSprites.Length). When Start is greater than that frame count the sequence would begin past the end of the file, so loading aborts with a YamlException rather than producing an empty/broken cursor.

Source

Thrown at OpenRA.Game/Graphics/CursorManager.cs:65

			SheetBuilder = new SheetBuilder(SheetType.BGRA, modData.Manifest.RendererConstants.CursorSheetSize);

			// Overwrite previous definitions if there are duplicates
			var pals = new Dictionary<string, IProvidesCursorPaletteInfo>();
			foreach (var p in modData.DefaultRules.Actors[SystemActors.World].TraitInfos<IProvidesCursorPaletteInfo>())
				if (p.Palette != null)
					pals[p.Palette] = p;

			var paletteCache = new Cache<string, ImmutablePalette>(p => pals[p].ReadPalette(modData.DefaultFileSystem));
			var frameCache = new FrameCache(modData.DefaultFileSystem, modData.SpriteLoaders);

			// Sort the cursors for better packing onto the sheet.
			foreach (var kv in modData.Cursors)
			{
				var cursorSprites = frameCache[kv.Value.Src];
				var length = kv.Value.Length ?? cursorSprites.Length - kv.Value.Start;

				if (kv.Value.Start > cursorSprites.Length)
					throw new YamlException($"Cursor {kv.Value.Name}: {nameof(kv.Value.Start)} is greater than the length of the sprite sequence.");

				if (kv.Value.Length > cursorSprites.Length)
					throw new YamlException($"Cursor {kv.Value.Name}: {nameof(kv.Value.Length)} is greater than the length of the sprite sequence.");

				var frames = cursorSprites.Skip(kv.Value.Start).Take(length).ToArray();
				var palette = !string.IsNullOrEmpty(kv.Value.Palette) ? paletteCache[kv.Value.Palette] : null;

				var c = new Cursor
				{
					Name = kv.Key,
					Bounds = Rectangle.FromLTRB(0, 0, 1, 1),

					Length = 0,
					Sprites = new Sprite[frames.Length],
					Cursors = new IHardwareCursor[frames.Length]
				};

				// Hardware cursors have a number of odd platform-specific bugs/limitations.

View on GitHub (pinned to a520984d91)

Solutions

  1. Open the sprite file referenced by the cursor's Src and count its frames; set Start to a value at or below that count (Start == length is accepted but yields zero frames, so prefer strictly less).
  2. If Start is correct, replace Src with a sprite file that actually contains at least Start+1 frames.
  3. Run 'OpenRA.Utility <mod> --check-cursors' (or the mod's validation utility) to flag out-of-range Start values before launching the game.

Example fix

# cursor.yaml (before)
cursor:
  Src: bits/cursor.shp
  Start: 12
# the .shp only has 8 frames -> reduce Start
# cursor.yaml (after)
cursor:
  Src: bits/cursor.shp
  Start: 4
Defensive patterns

Strategy: validation

Validate before calling

// Before relying on a cursor sequence, verify Start against the sprite frame count.
var frames = frameCache[cursorSeq.Src];
if (cursorSeq.Start > frames.Length)
    throw new InvalidOperationException($"Cursor {cursorSeq.Name}: Start {cursorSeq.Start} exceeds {frames.Length} frames in {cursorSeq.Src}");

Prevention

When it happens

Trigger: Produced by CursorManager's constructor loop over modData.Cursors: 'if (kv.Value.Start > cursorSprites.Length) throw'. Any cursor sequence whose Src sprite yields fewer frames than the declared Start value triggers it during mod load.

Common situations: Cursor YAML points Start at a frame index that does not exist in the .shp/.png sprite (off-by-one, or the sprite was replaced with a shorter one). Renumbering frames after editing a sprite sheet, or copying a cursor definition from another mod whose sprite has a different frame count.

Related errors


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