Unity-Technologies/ml-agents · error · KeyError

has type ( , )

Error message

{key} has type ({type(key0)}, {type(key1)})

What it means

AgentBuffer._check_key validates that tuple keys have well-typed components. An ObservationKeyPrefix must be paired with an int index; anything else raises this KeyError. The message shows the actual types of both tuple elements so you can see which one is wrong.

Solutions

  1. Use the key factory helpers (AgentBufferField keys like ObsGroupKey / ObservationKeyPrefix(name, int_index)) instead of building tuples manually
  2. Ensure the second element of the tuple with an ObservationKeyPrefix is an int (e.g. int(suffix))
  3. If the key came from a string, decode it with AgentBuffer._decode_key rather than splitting it yourself

Example fix

// before
key = (ObservationKeyPrefix('VectorObservation'), '3')
field = buffer[key]
// after
key = (ObservationKeyPrefix('VectorObservation'), 3)
field = buffer[key]
Defensive patterns

Strategy: type-guard

Validate before calling

def is_valid_buffer_key(key):
    if isinstance(key, tuple) and len(key) == 2:
        k0, k1 = key
        if isinstance(k0, ObservationKeyPrefix):
            return isinstance(k1, int)
        if isinstance(k0, RewardSignalKeyPrefix):
            return isinstance(k1, str)
    return False
# call buffer ops only if is_valid_buffer_key(key)

Type guard

def is_obs_key(key) -> bool:
    return (isinstance(key, tuple) and len(key) == 2
            and isinstance(key[0], ObservationKeyPrefix)
            and isinstance(key[1], int))

Try / catch

try:
    field = buffer[key]
except KeyError as e:
    logger.error(f"Invalid buffer key {key}: {e}")
    field = None

Prevention

When it happens

Trigger: Indexing an AgentBuffer with a tuple like (ObservationKeyPrefix('VectorObservation'), 'not-an-int') via __getitem__, __setitem__, __delitem__, __contains__ or check_length, e.g. buffer[ObsGroupKey('name', '0')] or passing a str suffix instead of int.

Common situations: Hand-constructing buffer keys after a refactor, deserializing keys from a saved file without _decode_key, or mixing up the int suffix of ObservationKeyPrefix keys with the str suffix of RewardSignalKeyPrefix keys.

Related errors


AI-assisted analysis of Unity-Technologies/ml-agents@3ecb446f75 (2026-09-02). Data as JSON: /api/errors/71118d76da2fb196. Report an issue: GitHub.

Appendix: source

Thrown at ml-agents/mlagents/trainers/buffer.py:292

    def reset_agent(self) -> None:
        """
        Resets the AgentBuffer
        """
        for f in self._fields.values():
            f.reset_field()
        self.last_brain_info = None
        self.last_take_action_outputs = None

    @staticmethod
    def _check_key(key):
        if isinstance(key, BufferKey):
            return
        if isinstance(key, tuple):
            key0, key1 = key
            if isinstance(key0, ObservationKeyPrefix):
                if isinstance(key1, int):
                    return
                raise KeyError(f"{key} has type ({type(key0)}, {type(key1)})")
            if isinstance(key0, RewardSignalKeyPrefix):
                if isinstance(key1, str):
                    return
                raise KeyError(f"{key} has type ({type(key0)}, {type(key1)})")
        raise KeyError(f"{key} is a {type(key)}")

    @staticmethod
    def _encode_key(key: AgentBufferKey) -> str:
        """
        Convert the key to a string representation so that it can be used for serialization.
        """
        if isinstance(key, BufferKey):
            return key.value
        prefix, suffix = key
        return f"{prefix.value}:{suffix}"

    @staticmethod
    def _decode_key(encoded_key: str) -> AgentBufferKey:

View on GitHub (pinned to 3ecb446f75)