microsoft/qlib · error · ValueError
Unsupported value to fill with invalid: {obj}
Error message
Unsupported value to fill with invalid: {obj} What it means
ValueError from `fill_invalid` in qlib/rl/utils/finite_env.py:55. The function recursively builds an 'invalid' sentinel sample matching a space's structure: it supports np.ndarray, numpy scalars, dict, list, and tuple; any other type (str, None, custom object, plain python int/float for the array branch) reaches the final raise.
Source
Thrown at qlib/rl/utils/finite_env.py:55
def fill_invalid(obj: int | float | bool | T) -> T:
if isinstance(obj, (int, float, bool)):
return fill_invalid(np.array(obj))
if hasattr(obj, "dtype"):
if isinstance(obj, np.ndarray):
if np.issubdtype(obj.dtype, np.floating):
return np.full_like(obj, np.nan)
return np.full_like(obj, np.iinfo(obj.dtype).max)
# dealing with corner cases that numpy number is not supported by tianshou's sharray
return fill_invalid(np.array(obj))
elif isinstance(obj, dict):
return {k: fill_invalid(v) for k, v in obj.items()}
elif isinstance(obj, list):
return [fill_invalid(v) for v in obj]
elif isinstance(obj, tuple):
return tuple(fill_invalid(v) for v in obj)
raise ValueError(f"Unsupported value to fill with invalid: {obj}")
def is_invalid(arr: int | float | bool | T) -> bool:
if isinstance(arr, np.ndarray):
if np.issubdtype(arr.dtype, np.floating):
return np.isnan(arr).all()
return cast(bool, cast(np.ndarray, np.iinfo(arr.dtype).max == arr).all())
if isinstance(arr, dict):
return all(is_invalid(o) for o in arr.values())
if isinstance(arr, (list, tuple)):
return all(is_invalid(o) for o in arr)
if isinstance(arr, (int, float, bool, np.number)):
return is_invalid(np.array(arr))
return True
def generate_nan_observation(obs_space: gym.Space) -> Any:
"""The NaN observation that indicates the environment receives no seed.View on GitHub (pinned to 79633dd950)
Solutions
- Keep observation leaves to numeric ndarray/dict/list/tuple structures; move string metadata out of the observation (put it in simulator state or info).
- Convert leaves to np.ndarray explicitly in your StateInterpreter (`np.asarray(x, dtype=np.float32)`), including scalars to 0-d/1-element arrays.
- Drop None-valued keys or replace them with NaN-filled numeric arrays so fill_invalid can recurse.
Example fix
// before
obs = {"feature": feat, "stock_id": "SH600000"} # str leaf -> ValueError
// after
obs = {"feature": feat, "stock_id": np.asarray(600000, dtype=np.int64)} # numeric leaf Defensive patterns
Strategy: type-guard
Validate before calling
import numpy as np
def leaves_fillable(obj) -> bool:
if isinstance(obj, np.ndarray):
return obj.dtype == object or np.issubdtype(obj.dtype, np.number) or np.issubdtype(obj.dtype, np.bool_)
if isinstance(obj, np.number):
return True
if isinstance(obj, dict):
return all(leaves_fillable(v) for v in obj.values())
if isinstance(obj, (list, tuple)):
return all(leaves_fillable(v) for v in obj)
return False Type guard
def fill_invalid_safe(obj):
"""Pre-convert unsupported leaves so fill_invalid never raises."""
if isinstance(obj, (str, bytes, type(None))):
return np.asarray(0, dtype=np.int64)
if isinstance(obj, (int, float, bool)):
return np.asarray(obj)
if isinstance(obj, dict):
return {k: fill_invalid_safe(v) for k, v in obj.items()}
if isinstance(obj, (list, tuple)):
return type(obj)(fill_invalid_safe(v) for v in obj)
return obj Try / catch
try:
invalid = fill_invalid(obs)
except ValueError as e:
if "Unsupported value to fill with invalid" in str(e):
raise TypeError(f"observation leaf not fillable: {e}") from e
raise Prevention
- Keep observations purely numeric (ndarray/dict/list/tuple of numbers).
- Convert str/None metadata out of the observation in the StateInterpreter.
- Test fill_invalid on a real sample when adding new observation fields.
When it happens
Trigger: An observation/space sample containing an unsupported leaf: a string id (e.g. stock_id), a None value, a python object, or a bare python int/float that the numpy conversion path can't turn into a supported array (or an empty/zero-d object array).
Common situations: Custom observations that embed metadata (dates as str, instrument ids, enums); gym version changes making samples come back as object dtype arrays; observations containing None for optional fields.
Related errors
- Unsupported policy type: {type(policy)}.
- Network path not found
- Unsupported reweighter type.
- Unsupported reweighter type.
- Unsupported reweighter type.
AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15).
Data as JSON: /api/errors/cfecf6cf89190fea.
Report an issue: GitHub.