{"record":{"id":"8ca5bbb740825961","repo":"microsoft/qlib","slug":"seed-iterator-for-validation-is-not-available","errorCode":null,"errorMessage":"Seed iterator for validation is not available.","messagePattern":"Seed iterator for validation is not available\\.","errorType":"exception","errorClass":"SeedIteratorNotAvailable","httpStatus":null,"severity":"error","filePath":"qlib/rl/trainer/vessel.py","lineNumber":60,"sourceCode":"    simulator_fn: Callable[[InitialStateType], Simulator[InitialStateType, StateType, ActType]]\n    state_interpreter: StateInterpreter[StateType, ObsType]\n    action_interpreter: ActionInterpreter[StateType, PolicyActType, ActType]\n    policy: BasePolicy\n    reward: Reward\n    trainer: Trainer\n\n    def assign_trainer(self, trainer: Trainer) -> None:\n        self.trainer = weakref.proxy(trainer)  # type: ignore\n\n    def train_seed_iterator(self) -> ContextManager[Iterable[InitialStateType]] | Iterable[InitialStateType]:\n        \"\"\"Override this to create a seed iterator for training.\n        If the iterable is a context manager, the whole training will be invoked in the with-block,\n        and the iterator will be automatically closed after the training is done.\"\"\"\n        raise SeedIteratorNotAvailable(\"Seed iterator for training is not available.\")\n\n    def val_seed_iterator(self) -> ContextManager[Iterable[InitialStateType]] | Iterable[InitialStateType]:\n        \"\"\"Override this to create a seed iterator for validation.\"\"\"\n        raise SeedIteratorNotAvailable(\"Seed iterator for validation is not available.\")\n\n    def test_seed_iterator(self) -> ContextManager[Iterable[InitialStateType]] | Iterable[InitialStateType]:\n        \"\"\"Override this to create a seed iterator for testing.\"\"\"\n        raise SeedIteratorNotAvailable(\"Seed iterator for testing is not available.\")\n\n    def train(self, vector_env: BaseVectorEnv) -> Dict[str, Any]:\n        \"\"\"Implement this to train one iteration. In RL, one iteration usually refers to one collect.\"\"\"\n        raise NotImplementedError()\n\n    def validate(self, vector_env: FiniteVectorEnv) -> Dict[str, Any]:\n        \"\"\"Implement this to validate the policy once.\"\"\"\n        raise NotImplementedError()\n\n    def test(self, vector_env: FiniteVectorEnv) -> Dict[str, Any]:\n        \"\"\"Implement this to evaluate the policy on test environment once.\"\"\"\n        raise NotImplementedError()\n\n    def log(self, name: str, value: Any) -> None:","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/rl/trainer/vessel.py#L42-L78","documentation":"SeedIteratorNotAvailable from the default `Vessel.val_seed_iterator` (qlib/rl/trainer/vessel.py:60). Same abstract-method contract as the training variant, but for the validation set: the trainer fetches validation initial states from this hook when running validation during/after training.","triggerScenarios":"A vessel without a `val_seed_iterator` override used with `Trainer.fit(...)` while `num_episode`/callbacks request validation, or an explicit `trainer.validate(vessel)` call.","commonSituations":"Teams implement training seeds first and forget validation; validation intended to reuse the train iterator but the hook was never wired; EarlyStopping callback configured with a monitor, which forces validation and surfaces the missing override.","solutions":["Override `val_seed_iterator` to return the iterable of validation initial states (typically a held-out date/order split).","If you don't want validation, remove validation-triggering callbacks/arguments rather than letting the exception fire.","To reuse training data for validation, return the same generator factory (fresh instance, not an exhausted iterator)."],"exampleFix":"// before\nclass MyVessel(Vessel):\n    def train_seed_iterator(self): return iter(train_orders)\n    # val_seed_iterator missing -> error when EarlyStopping validates\n// after\nclass MyVessel(Vessel):\n    def train_seed_iterator(self): return iter(train_orders)\n    def val_seed_iterator(self): return iter(val_orders)","handlingStrategy":"validation","validationCode":"from qlib.rl.trainer.vessel import Vessel\n\ndef val_seeds_available(vessel: Vessel) -> bool:\n    return type(vessel).val_seed_iterator is not Vessel.val_seed_iterator","typeGuard":"def vessel_supports_validation(v) -> bool:\n    from qlib.rl.trainer.vessel import Vessel\n    return type(v).val_seed_iterator is not Vessel.val_seed_iterator","tryCatchPattern":"from qlib.rl.trainer.vessel import SeedIteratorNotAvailable\ntry:\n    trainer.validate(vessel)\nexcept SeedIteratorNotAvailable:\n    log.warning(\"no validation seed iterator; skipping validation\")","preventionTips":["If using EarlyStopping or any monitor callback, implement val_seed_iterator from day one.","Split data into train/val/test seed sets up front and wire all three hooks.","Return fresh generator factories, not shared exhausted iterators."],"tags":["rl","trainer","vessel","validation","not-implemented"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}