microsoft/qlib · error · GymSpaceValidationError
Sample must be a dict with same length as space.
Error message
Sample must be a dict with same length as space.
What it means
_gym_space_contains (qlib/rl/interpreter.py:109) is a hardened replacement for gym.Space.contains used to validate action/observation samples against the declared gym space. For gym.spaces.Dict spaces, the sample must be a dict with exactly the same number of keys as the space; otherwise it raises GymSpaceValidationError('Sample must be a dict with same length as space.') instead of returning a boolean, so the exact mismatch is visible.
Source
Thrown at qlib/rl/interpreter.py:109
action
Raw action given by policy.
Returns
-------
The action needed by simulator,
"""
raise NotImplementedError("interpret is not implemented!")
def _gym_space_contains(space: gym.Space, x: Any) -> None:
"""Strengthened version of gym.Space.contains.
Giving more diagnostic information on why validation fails.
Throw exception rather than returning true or false.
"""
if isinstance(space, spaces.Dict):
if not isinstance(x, dict) or len(x) != len(space):
raise GymSpaceValidationError("Sample must be a dict with same length as space.", space, x)
for k, subspace in space.spaces.items():
if k not in x:
raise GymSpaceValidationError(f"Key {k} not found in sample.", space, x)
try:
_gym_space_contains(subspace, x[k])
except GymSpaceValidationError as e:
raise GymSpaceValidationError(f"Subspace of key {k} validation error.", space, x) from e
elif isinstance(space, spaces.Tuple):
if isinstance(x, (list, np.ndarray)):
x = tuple(x) # Promote list and ndarray to tuple for contains check
if not isinstance(x, tuple) or len(x) != len(space):
raise GymSpaceValidationError("Sample must be a tuple with same length as space.", space, x)
for i, (subspace, part) in enumerate(zip(space, x)):
try:
_gym_space_contains(subspace, part)
except GymSpaceValidationError as e:
raise GymSpaceValidationError(f"Subspace of index {i} validation error.", space, x) from eView on GitHub (pinned to 79633dd950)
Solutions
- Make the interpreter's returned sample a dict whose keys exactly match the space's keys (same count, same names)
- Update the gym.spaces.Dict definition and the interpreter together when the action schema changes
- Validate with _gym_space_contains(space, sample) in interpreter unit tests before running the simulator
Example fix
# before
# space = gym.spaces.Dict({'amount': gym.spaces.Box(...)})
sample = np.array([0.5]) # not a dict -> GymSpaceValidationError
action = interpreter.to_action(sample)
# after
sample = {'amount': np.array([0.5], dtype=np.float32)}
action = interpreter.to_action(sample) Defensive patterns
Strategy: validation
Validate before calling
from gym import spaces assert isinstance(sample, dict) and len(sample) == len(space.spaces), 'sample must match Dict space keys'
Type guard
def matches_dict_space(sample, space) -> bool:
return isinstance(sample, dict) and set(sample.keys()) == set(space.spaces.keys()) Try / catch
try:
_gym_space_contains(space, sample)
except GymSpaceValidationError as e:
logger.error('interpreter sample rejected: %s', e)
raise Prevention
- Keep interpreter output schemas and gym space definitions in one module and change them together
- Add a unit test per interpreter asserting sample/space compatibility via _gym_space_contains
When it happens
Trigger: An RL interpreter (action interpreter of the QlibRLSimulator, e.g. Categorical-Interpreter outputs) produces a sample that is not a dict, or a dict with extra/missing keys relative to the nested gym Dict space; custom interpreters returning plain arrays for Dict-typed action spaces.
Common situations: Writing a custom qlib.rl simulator/interpreter whose to_action_* return type drifts from the declared action space; changing the gym space definition (adding/removing keys like 'amount') without updating the interpreter; gym version differences changing space.spaces contents.
Related errors
- Key {k} not found in sample.
- Subspace of key {k} validation error.
- Sample must be a tuple with same length as space.
- Subspace of index {i} validation error.
- Validation error reported by gym.
AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15).
Data as JSON: /api/errors/a783298055737178.
Report an issue: GitHub.