Unity-Technologies/ml-agents · error · IndexOutOfRangeException
channel value {ch} must be in range [0, {m_TensorShape.Chann
Error message
channel value {ch} must be in range [0, {m_TensorShape.Channels() - 1}] What it means
ObservationWriter's indexed setter validates that the channel coordinate falls within the observation tensor's channel count before writing. Writing outside that range would overwrite neighboring observations in the flat backing array, so an IndexOutOfRangeException is thrown.
Source
Thrown at com.unity.ml-agents/Runtime/Sensors/ObservationWriter.cs:152
public float this[int ch, int h, int w]
{
set
{
if (m_Data != null)
{
if (h < 0 || h >= m_TensorShape.Height())
{
throw new IndexOutOfRangeException($"height value {h} must be in range [0, {m_TensorShape.Height() - 1}]");
}
if (w < 0 || w >= m_TensorShape.Width())
{
throw new IndexOutOfRangeException($"width value {w} must be in range [0, {m_TensorShape.Width() - 1}]");
}
if (ch < 0 || ch >= m_TensorShape.Channels())
{
throw new IndexOutOfRangeException($"channel value {ch} must be in range [0, {m_TensorShape.Channels() - 1}]");
}
var index = m_TensorShape.Index(m_Batch, ch + m_Offset, h, w);
m_Data[index] = value;
}
else
{
if (ch + m_Offset < 0 || ch + m_Offset >= m_TensorShape.Channels() ||
h < 0 || h >= m_TensorShape.Height() ||
w < 0 || w >= m_TensorShape.Width())
return;
m_Proxy.data.CompleteAllPendingOperations();
((Tensor<float>)m_Proxy.data)[m_Batch, ch + m_Offset, h, w] = value;
}
}
}
View on GitHub (pinned to 3ecb446f75)
Solutions
- Limit the channel loop to spec.Channels() (and respect the writer's offset for stacked writers)
- Make the ObservationSpec channel count match the data written (e.g. 3 for RGB, 1 for grayscale)
- Use ObservationWriter helper APIs (WriteTex2D/Add) that handle channels and offsets correctly
- Check for off-by-one loops (ch <= channels instead of ch < channels)
Example fix
// before for (int ch = 0; ch < 4; ch++) writer[0, 0, ch] = rgba[ch]; // spec has 3 channels // after for (int ch = 0; ch < obsSpec.Channels(); ch++) writer[0, 0, ch] = rgba[ch];
Defensive patterns
Strategy: validation
Validate before calling
// Unity C#: in custom sensor Write
if (ch < 0 || ch >= obsSpec.Channels())
{
Debug.LogError($"ch={ch} outside [0,{obsSpec.Channels() - 1}]");
return;
}
writer[h, w, ch] = value; Try / catch
try
{
writer[h, w, ch] = value;
}
catch (IndexOutOfRangeException e) when (e.Message.Contains("channel value"))
{
Debug.LogError("Channel out of bounds writing observation: " + e.Message);
} Prevention
- Limit channel loops to spec.Channels() (RGB=3, grayscale=1) and respect the writer offset
- Keep the ObservationSpec channel count in sync with the data actually written
- Use ObservationWriter helper methods (WriteTex2D/Add) that handle channels and offsets
When it happens
Trigger: A custom sensor's Write() implementation calling Write(h, w, ch, value) with ch < 0 or ch >= channel count (e.g. writing RGB with 3 channels while the spec declares 1 channel, or writing a 4-channel RGBA loop); m_Offset plus ch exceeding the declared channels.
Common situations: Custom sensors writing RGBA into a grayscale observation; stacked sensors where the offset wasn't accounted for; changing channel count in the spec but not in the write loop.
Related errors
- height value {h} must be in range [0, {m_TensorShape.Height(
- width value {w} must be in range [0, {m_TensorShape.Width()
- row was {row}, but must be between 0 and {maxBoardSize.Rows
- col was {col}, but must be between 0 and {maxBoardSize.Colum
- Cannot move cell at row={row} col={col} in Direction={dir}
AI-assisted analysis of Unity-Technologies/ml-agents@3ecb446f75 (2026-09-02).
Data as JSON: /api/errors/221a5ea5061c6124.
Report an issue: GitHub.