OpenRA/OpenRA · error · LuaException
Layer {layer} does not exist on this map. Valid layers on th
Error message
Layer {layer} does not exist on this map. Valid layers on this map are: {string.Join(", ", validLayers.Select(x => $"{x.Index} ({x.Name})"))} What it means
When constructing a CPos with a non-zero layer, the engine checks the world's custom movement layers array; if the index is out of range or that slot is null (no layer registered at that index) it lists the valid layers by index and name and aborts.
Source
Thrown at OpenRA.Mods.Common/Scripting/Global/CoordinateGlobals.cs:44
[Desc("Create a new CPos with the specified coordinates on the specified layer. " +
"The ground is layer 0, other layers have a unique ID. Examples include tunnels, underground, and elevated bridges.")]
public CPos NewWithLayer(int x, int y, byte layer)
{
if (layer != 0)
{
var worldCmls = Context.World.GetCustomMovementLayers();
if (layer >= worldCmls.Length || worldCmls[layer] == null)
{
var layerNames = typeof(CustomMovementLayerType)
.GetFields()
.Select(f => (Index: (byte)f.GetRawConstantValue(), f.Name))
.ToArray();
var validLayers = new[] { (Index: (byte)0, Name: "Ground") }
.Concat(worldCmls
.Where(cml => cml != null)
.Select(cml => layerNames.Single(ln => ln.Index == cml.Index)));
throw new LuaException($"Layer {layer} does not exist on this map. " +
$"Valid layers on this map are: {string.Join(", ", validLayers.Select(x => $"{x.Index} ({x.Name})"))}");
}
}
return new CPos(x, y, layer);
}
[Desc("The cell coordinate origin.")]
public CPos Zero => CPos.Zero;
}
[ScriptGlobal("CVec")]
public class CVecGlobal : ScriptGlobal
{
public CVecGlobal(ScriptContext context)
: base(context) { }
[Desc("Create a new CVec with the specified coordinates.")]View on GitHub (pinned to a520984d91)
Solutions
- Read the valid layers from the error message and use one of those indices.
- Use layer 0 (Ground) when no custom layer is needed.
- Ensure the map includes the movement-layer trait (e.g. TunnelLayer, BridgeLayer) if a custom layer is required.
Example fix
-- before local p = CPos.New(5, 5, 2) -- layer 2 not on this map -- after local p = CPos.New(5, 5, 0) -- Ground layer -- or use a valid layer index from the error's list
Defensive patterns
Strategy: validation
Validate before calling
-- Use layer 0 (Ground) unless a known custom layer index is required.
local function SafeCPos(x, y, layer)
layer = layer or 0
if layer ~= 0 and not ValidLayers[layer] then
layer = 0
end
return CPos.New(x, y, layer)
end Type guard
local function IsValidLayer(idx) return type(idx) == "number" and (idx == 0 or ValidLayers[idx] == true) end
Try / catch
local ok, p = pcall(CPos.New, x, y, layer) if not ok then return CPos.New(x, y, 0) end
Prevention
- Default to ground layer (0).
- Cache the map's valid layer indices at script init.
- Avoid hardcoding custom layer indices across maps.
When it happens
Trigger: Calling CPos.New(x, y, layer) with a layer index for a custom movement layer (e.g. tunnels, bridges) that the map does not provide; passing an index beyond the registered layers.
Common situations: Map without the required custom-layer traits; using a layer index valid in one map but not another; stale index after the map's layers changed.
Related errors
- Unknown initializer type '{initInstance[0]}'
- Unknown initializer type '{initInstance[0]}.{key}'
- Invalid data type for '{initInstance[0]}.{key}' (expected {t
- Invalid data type for '{initInstance[0]}' (expected one of {
- Tried to create actor '{type}' with an invalid or no owner i
AI-assisted analysis of OpenRA/OpenRA@a520984d91 (2026-08-13).
Data as JSON: /api/errors/6c058d2a99c64187.
Report an issue: GitHub.