{"record":{"id":"ba5001abdd9ec153","repo":"microsoft/qlib","slug":"render-is-not-implemented-in-envwrapper","errorCode":null,"errorMessage":"Render is not implemented in EnvWrapper.","messagePattern":"Render is not implemented in EnvWrapper\\.","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"warning","filePath":"qlib/rl/utils/env_wrapper.py","lineNumber":250,"sourceCode":"        self.status[\"reward_history\"].append(rew)\n\n        if self.aux_info_collector is not None:\n            aux_info = self.aux_info_collector(sim_state)\n        else:\n            aux_info = {}\n\n        # Final logging stuff: RL-specific logs\n        if done:\n            self.logger.add_scalar(\"steps_per_episode\", self.status[\"cur_step\"])\n        self.logger.add_scalar(\"reward\", rew)\n        self.logger.add_any(\"obs\", obs, loglevel=LogLevel.DEBUG)\n        self.logger.add_any(\"policy_act\", policy_action, loglevel=LogLevel.DEBUG)\n\n        info_dict = InfoDict(log=self.logger.logs(), aux_info=aux_info)\n        return obs, rew, done, info_dict\n\n    def render(self, mode: str = \"human\") -> None:\n        raise NotImplementedError(\"Render is not implemented in EnvWrapper.\")\n","sourceCodeStart":232,"sourceCodeEnd":251,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/rl/utils/env_wrapper.py#L232-L251","documentation":"NotImplementedError from `EnvWrapper.render` (qlib/rl/utils/env_wrapper.py:250). The wrapper proxies reset/step to the underlying simulator plus interpreters, but rendering was never implemented, so any call — including generic RL tooling that renders by default — fails.","triggerScenarios":"Calling `env.render()` or `env.render('human')` directly; using a tianshou/gym runner or experiment tracker with `render=True`; gym API conformance checks or wrappers that invoke render on reset/step.","commonSituations":"Reusing generic gym visualization utilities with qlib's wrapper; watch/monitor wrappers (RecordVideo etc.) applied around EnvWrapper; porting tutorial code from other gym environments that call render in the loop.","solutions":["Remove render calls; inspect simulator state and `logger` metrics (wrapper logs obs/reward per step) instead.","Use the wrapper's `info_dict['log']` / LoggerWriter outputs to visualize training.","If rendering is essential, subclass EnvWrapper and implement `render` from `self.simulator.get_state()` for your task."],"exampleFix":"// before\nobs, rew, done, info = env.step(act)\nenv.render()  // NotImplementedError\n// after\nobs, rew, done, info = env.step(act)\nprint(info[\"log\"])  # use logged metrics instead of rendering","handlingStrategy":"type-guard","validationCode":"def supports_render(env) -> bool:\n    return type(env).render is not object.__getattribute__(env, \"render\").__func__  # simplified\n# simpler and sufficient:\ndef supports_render(env) -> bool:\n    import inspect\n    try:\n        return \"Not implemented\" not in inspect.getsource(type(env).render)\n    except (OSError, TypeError):\n        return True","typeGuard":"from qlib.rl.utils.env_wrapper import EnvWrapper\n\ndef env_supports_render(env) -> bool:\n    return not isinstance(env, EnvWrapper) or type(env).render is not EnvWrapper.render","tryCatchPattern":"try:\n    env.render(mode=mode)\nexcept NotImplementedError:\n    log.debug(\"render unsupported; skipping visualization\")","preventionTips":["Disable render in generic runners/watchers when using EnvWrapper.","Visualize via the wrapper's logged metrics (info_dict['log']) instead.","Subclass EnvWrapper and implement render from simulator state if you need visuals."],"tags":["rl","env-wrapper","render","not-implemented"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}