microsoft/qlib · error · GymSpaceValidationError

Subspace of key {k} validation error.

Error message

Subspace of key {k} validation error.

What it means

Wrapping error from qlib's recursive gym space validator (qlib/rl/interpreter.py:116). It is raised only as a re-raise: the sub-value `x[k]` of a Dict space failed validation in a nested call to `_gym_space_contains`, and the outer call decorates the original error with the offending key. The true root cause is in the exception chain (`__cause__`), not this message.

Source

Thrown at qlib/rl/interpreter.py:116

        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 e

    else:
        if not space.contains(x):
            raise GymSpaceValidationError("Validation error reported by gym.", space, x)


class GymSpaceValidationError(Exception):

View on GitHub (pinned to 79633dd950)

Solutions

  1. Inspect the chained exception (`except GymSpaceValidationError as e: print(e.__cause__)`) to find the leaf-level failure and which key path led there.
  2. Fix the leaf value: clamp/normalize the action or observation so it satisfies the inner space's bounds/shape.
  3. If the inner space bounds are wrong, widen or re-derive `action_space`/`observation_space` in your interpreter.

Example fix

// before
action_space = spaces.Box(-1.0, 1.0, shape=(1,))
act = np.array([1.7])  # out of bounds -> nested validation fails, wrapped as 'Subspace of key ...'
// after
act = np.clip(raw_act, -1.0, 1.0)  # satisfy inner Box bounds
Defensive patterns

Strategy: try-catch

Validate before calling

from qlib.rl.interpreter import _gym_space_contains
_gym_space_contains(space, sample)  # run in tests before starting training

Type guard

def leaf_in_bounds(box: gym.spaces.Box, v) -> bool:
    import numpy as np
    v = np.asarray(v, dtype=box.dtype)
    return v.shape == box.shape and (v >= box.low).all() and (v <= box.high).all()

Try / catch

try:
    _gym_space_contains(space, x)
except GymSpaceValidationError as e:
    cause = e.__cause__ or e
    log.error("key-path failure: %s | root cause: %s", e.message, cause)
    raise

Prevention

When it happens

Trigger: A `spaces.Dict` space whose value for key `k` is itself a Dict/Tuple/Box, and `x[k]` fails the nested check: wrong length tuple, out-of-bounds Box value, missing nested key, etc. Example: `spaces.Dict({"obs": spaces.Box(-1, 1)})` with `x["obs"] = 2.5`.

Common situations: Nested observation spaces in custom order-execution interpreters; actions outside the declared action Box (e.g. interpreter yields >1 for a Box(-1,1) action space); dtype mismatches inside nested structures.

Related errors


AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15). Data as JSON: /api/errors/d5d00c71859233f1. Report an issue: GitHub.