{"record":{"id":"139acda22173ff95","repo":"OpenRA/OpenRA","slug":"chronoshift-requires-a-table-of-actor-cpos-pairs","errorCode":null,"errorMessage":"Chronoshift requires a table of actor,cpos pairs. Received {kv.Key.WrappedClrType().Name},{kv.Value.WrappedClrType().Name}","messagePattern":"Chronoshift requires a table of actor,cpos pairs\\. Received (.+?),(.+?)","errorType":"exception","errorClass":"LuaException","httpStatus":null,"severity":"error","filePath":"OpenRA.Mods.Cnc/Scripting/Properties/ChronosphereProperties.cs","lineNumber":38,"sourceCode":"\t[ScriptPropertyGroup(\"Support Powers\")]\n\tpublic class ChronosphereProperties : ScriptActorProperties, Requires<ChronoshiftPowerInfo>\n\t{\n\t\tpublic ChronosphereProperties(ScriptContext context, Actor self)\n\t\t\t: base(context, self) { }\n\n\t\t[Desc(\"Chronoshift a group of actors. A duration of 0 will teleport the actors permanently. \" +\n\t\t\t\"If a given cell is unexplored for this power's owner, the closest valid cell will be used instead.\")]\n\t\tpublic void Chronoshift([ScriptEmmyTypeOverride(\"{ [actor]: cpos }\")] LuaTable unitLocationPairs, int duration = 0, bool killCargo = false)\n\t\t{\n\t\t\tforeach (var kv in unitLocationPairs)\n\t\t\t{\n\t\t\t\tActor actor;\n\t\t\t\tCPos cell;\n\t\t\t\tusing (kv.Key)\n\t\t\t\tusing (kv.Value)\n\t\t\t\t{\n\t\t\t\t\tif (!kv.Key.TryGetClrValue(out actor) || !kv.Value.TryGetClrValue(out cell))\n\t\t\t\t\t\tthrow new LuaException($\"Chronoshift requires a table of actor,cpos pairs. Received {kv.Key.WrappedClrType().Name},{kv.Value.WrappedClrType().Name}\");\n\t\t\t\t}\n\n\t\t\t\tvar cs = actor.TraitsImplementing<Chronoshiftable>()\n\t\t\t\t\t.FirstEnabledConditionalTraitOrDefault();\n\n\t\t\t\tif (cs != null && cs.CanChronoshiftTo(actor, cell))\n\t\t\t\t\tcs.Teleport(actor, cell, duration, killCargo, Self);\n\t\t\t}\n\t\t}\n\t}\n}\n","sourceCodeStart":20,"sourceCodeEnd":50,"githubUrl":"https://github.com/OpenRA/OpenRA/blob/a520984d91eda9de48a62b1d15c1e3bad0d4fb1a/OpenRA.Mods.Cnc/Scripting/Properties/ChronosphereProperties.cs#L20-L50","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure the table keys are Actor objects obtained from the scripting API (e.g. Actor.Create or map-defined actors).","Ensure the table values are CPos values obtained from the map (e.g. Map.CellFromPosition or CPos.New).","Inspect the error message's type names to identify which key/value has the wrong type.","Validate the table contents in the script before calling Chronoshift."],"exampleFix":"-- before (Lua):\nChronosphere.Chronoshift({ [\"unit1\"] = \"5,5\" })\n\n-- after:\nlocal actor = Map.NamedActors[\"unit1\"]\nChronosphere.Chronoshift({ [actor] = CPos.New(5, 5) })","handlingStrategy":"validation","validationCode":"-- In Lua, validate table before calling:\nfor k, v in pairs(unitLocationPairs) do\n  if type(k) ~= \"table\" or k.WrappedClrType == nil then\n    error(\"Key must be an Actor\")\n  end\nend","typeGuard":"-- Lua guard:\nlocal function isValidChronoshiftTable(t)\n  for k, v in pairs(t) do\n    if not k.TryGetClrValue then return false end\n  end\n  return true\nend","tryCatchPattern":"local ok, err = pcall(function() Chronosphere.Chronoshift(pairs) end)\nif not ok then print(\"Chronoshift failed: \" .. tostring(err)) end","preventionTips":["Use Actor objects (not strings or IDs) as table keys.","Use CPos values (not raw numbers) as table values.","Validate table contents in a pcall to avoid crashing the script."],"tags":["scripting","lua","chronosphere","type-mismatch"],"backgroundTag":null,"analyzedSha":"a520984d91eda9de48a62b1d15c1e3bad0d4fb1a","analyzedAt":"2026-08-13T15:30:14.787Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}