{"record":{"id":"bdf6f529049c4fd2","repo":"microsoft/qlib","slug":"optimizer-is-not-supported-bdf6f5","errorCode":null,"errorMessage":"optimizer {} is not supported!","messagePattern":"optimizer (.+?) is not supported!","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"qlib/contrib/model/pytorch_sandwich.py","lineNumber":222,"sourceCode":"\n        self.sandwich_model = SandwichModel(\n            fea_dim=self.fea_dim,\n            cnn_dim_1=self.cnn_dim_1,\n            cnn_dim_2=self.cnn_dim_2,\n            cnn_kernel_size=self.cnn_kernel_size,\n            rnn_dim_1=self.rnn_dim_1,\n            rnn_dim_2=self.rnn_dim_2,\n            rnn_dups=self.rnn_dups,\n            rnn_layers=self.rnn_layers,\n            dropout=self.dropout,\n            device=self.device,\n        )\n        if optimizer.lower() == \"adam\":\n            self.train_optimizer = optim.Adam(self.sandwich_model.parameters(), lr=self.lr)\n        elif optimizer.lower() == \"gd\":\n            self.train_optimizer = optim.SGD(self.sandwich_model.parameters(), lr=self.lr)\n        else:\n            raise NotImplementedError(\"optimizer {} is not supported!\".format(optimizer))\n\n        self.fitted = False\n        self.sandwich_model.to(self.device)\n\n    @property\n    def use_gpu(self):\n        return self.device != torch.device(\"cpu\")\n\n    def mse(self, pred, label):\n        loss = (pred - label) ** 2\n        return torch.mean(loss)\n\n    def loss_fn(self, pred, label):\n        mask = ~torch.isnan(label)\n\n        if self.loss == \"mse\":\n            return self.mse(pred[mask], label[mask])\n","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/contrib/model/pytorch_sandwich.py#L204-L240","documentation":"Raised by the SANDWICH model's init in qlib/contrib/model/pytorch_sandwich.py:222 when the optimizer parameter, lowercased, is neither 'adam' nor 'gd'. 'gd' maps to torch.optim.SGD with the configured lr. Any other string (e.g. 'sgd', 'adamw', 'rmsprop') hits the else branch and raises NotImplementedError.","triggerScenarios":"Instantiating the sandwich model with optimizer='sgd' (the correct token is 'gd'), 'adamw', 'rmsprop', or any unsupported name; the raise happens during model construction, before fit().","commonSituations":"Muscle-memory 'sgd' from other frameworks — qlib's token is 'gd'; using optimizer settings copied from LightGBM/XGBoost model sections in the same workflow file.","solutions":["Set optimizer: 'adam' or 'gd' (gd = plain SGD at the given lr) in the model kwargs.","If you truly need AdamW/RMSProp, subclass and construct the optimizer yourself after super().__init__ with a supported placeholder value."],"exampleFix":"# before\nkwargs:\n  optimizer: sgd\n\n# after\nkwargs:\n  optimizer: gd   # plain SGD; or 'adam'","handlingStrategy":"validation","validationCode":"optimizer = config[\"optimizer\"]\nassert optimizer.lower() in (\"adam\", \"gd\"), f\"optimizer must be 'adam' or 'gd' (plain SGD), got {optimizer!r}\"","typeGuard":"def is_supported_optimizer(optimizer: str) -> bool:\n    return optimizer.lower() in (\"adam\", \"gd\")","tryCatchPattern":"try:\n    model = SandwichModel(**kwargs)\nexcept NotImplementedError as e:\n    if \"optimizer\" in str(e):\n        raise ValueError(\"Use optimizer='adam' or 'gd'; 'sgd' is not a valid token\") from e\n    raise","preventionTips":["Note qlib's non-obvious 'gd' token for plain SGD across all pytorch contrib models.","Validate optimizer strings centrally if you drive many models from one config schema."],"tags":["qlib","pytorch","optimizer","config","not-implemented","sandwich"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}