OpenRA/OpenRA · error · LuaException

Chronoshift requires a table of actor,cpos pairs. Received {

Error message

Chronoshift requires a table of actor,cpos pairs. Received {kv.Key.WrappedClrType().Name},{kv.Value.WrappedClrType().Name}

What it means

Thrown by the Chronoshift Lua scripting property when iterating over a LuaTable of actor→cell-position pairs and a key or value cannot be converted to an Actor or CPos respectively. The method expects a table mapping Actor objects to CPos (cell position) values; receiving any other types causes this error.

Source

Thrown at OpenRA.Mods.Cnc/Scripting/Properties/ChronosphereProperties.cs:38

	[ScriptPropertyGroup("Support Powers")]
	public class ChronosphereProperties : ScriptActorProperties, Requires<ChronoshiftPowerInfo>
	{
		public ChronosphereProperties(ScriptContext context, Actor self)
			: base(context, self) { }

		[Desc("Chronoshift a group of actors. A duration of 0 will teleport the actors permanently. " +
			"If a given cell is unexplored for this power's owner, the closest valid cell will be used instead.")]
		public void Chronoshift([ScriptEmmyTypeOverride("{ [actor]: cpos }")] LuaTable unitLocationPairs, int duration = 0, bool killCargo = false)
		{
			foreach (var kv in unitLocationPairs)
			{
				Actor actor;
				CPos cell;
				using (kv.Key)
				using (kv.Value)
				{
					if (!kv.Key.TryGetClrValue(out actor) || !kv.Value.TryGetClrValue(out cell))
						throw new LuaException($"Chronoshift requires a table of actor,cpos pairs. Received {kv.Key.WrappedClrType().Name},{kv.Value.WrappedClrType().Name}");
				}

				var cs = actor.TraitsImplementing<Chronoshiftable>()
					.FirstEnabledConditionalTraitOrDefault();

				if (cs != null && cs.CanChronoshiftTo(actor, cell))
					cs.Teleport(actor, cell, duration, killCargo, Self);
			}
		}
	}
}

View on GitHub (pinned to a520984d91)

Solutions

  1. Ensure the table keys are Actor objects obtained from the scripting API (e.g. Actor.Create or map-defined actors).
  2. Ensure the table values are CPos values obtained from the map (e.g. Map.CellFromPosition or CPos.New).
  3. Inspect the error message's type names to identify which key/value has the wrong type.
  4. Validate the table contents in the script before calling Chronoshift.

Example fix

-- before (Lua):
Chronosphere.Chronoshift({ ["unit1"] = "5,5" })

-- after:
local actor = Map.NamedActors["unit1"]
Chronosphere.Chronoshift({ [actor] = CPos.New(5, 5) })
Defensive patterns

Strategy: validation

Validate before calling

-- In Lua, validate table before calling:
for k, v in pairs(unitLocationPairs) do
  if type(k) ~= "table" or k.WrappedClrType == nil then
    error("Key must be an Actor")
  end
end

Type guard

-- Lua guard:
local function isValidChronoshiftTable(t)
  for k, v in pairs(t) do
    if not k.TryGetClrValue then return false end
  end
  return true
end

Try / catch

local ok, err = pcall(function() Chronosphere.Chronoshift(pairs) end)
if not ok then print("Chronoshift failed: " .. tostring(err)) end

Prevention

When it happens

Trigger: Calling the Chronoshift Lua method with a table whose keys are not Actor objects or whose values are not CPos values. TryGetClrValue<Actor> or TryGetClrValue<CPos> returns false, and the error reports the actual wrapped types.

Common situations: A map script passes string IDs instead of Actor objects; cell positions are passed as tables or numbers instead of CPos; the table is nested incorrectly; a script uses positional arguments instead of key-value pairs.

Related errors


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