{"record":{"id":"e5fe8766cbbf45bb","repo":"deepfakes/faceswap","slug":"learn-mask-has-been-selected-but-you-have-not-ch","errorCode":null,"errorMessage":"'Learn Mask' has been selected but you have not chosen a Mask to use. Please select a mask or disable 'Learn Mask'.","messagePattern":"'Learn Mask' has been selected but you have not chosen a Mask to use\\. Please select a mask or disable 'Learn Mask'\\.","errorType":"exception","errorClass":"FaceswapError","httpStatus":null,"severity":"error","filePath":"plugins/train/model/_base/model.py","lineNumber":72,"sourceCode":"        is the same for both sides of the model, then this can be a single 3 dimensional `tuple`.\n        If the inputs have different sizes for `\"A\"` and `\"B\"` this should be a `list` of 2 3\n        dimensional shape `tuples`, 1 for each side respectively.\"\"\"\n\n        self.color_order: T.Literal[\"bgr\", \"rgb\"] = \"bgr\"  # Override for image color channel order\n\n        self._args = arguments\n        self._is_predict = predict\n        self._model: keras.Model | None = None\n\n        cfg.load_config(config_file=arguments.config_file)\n\n        if cfg.Loss.penalized_mask_loss() and cfg.Loss.mask_type() == \"none\":\n            raise FaceswapError(\"Penalized Mask Loss has been selected but you have not chosen a \"\n                                \"Mask to use. Please select a mask or disable Penalized Mask \"\n                                \"Loss.\")\n\n        if cfg.Loss.learn_mask() and cfg.Loss.mask_type() == \"none\":\n            raise FaceswapError(\"'Learn Mask' has been selected but you have not chosen a Mask to \"\n                                \"use. Please select a mask or disable 'Learn Mask'.\")\n\n        self._mixed_precision = cfg.mixed_precision()\n        self._io = IO(self, model_dir,\n                      self._is_predict,\n                      T.cast(T.Literal[\"never\", \"always\", \"exit\"], cfg.Optimizer.save_optimizer()))\n        self._check_multiple_models()\n\n        self._state = State(model_dir,\n                            self.name,\n                            False if self._is_predict else self._args.no_logs)\n        self._settings = Settings(self._args,\n                                  self._mixed_precision,\n                                  self._is_predict)\n        logger.debug(\"Initialized ModelBase (%s)\", self.__class__.__name__)\n\n    @property\n    def model(self) -> keras.Model:","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/deepfakes/faceswap/blob/f530cb7508ae670f6474f8a7d9c4df94705cf96b/plugins/train/model/_base/model.py#L54-L90","documentation":"FaceswapError raised in the training ModelBase constructor when the loss configuration enables 'Learn Mask' (cfg.Loss.learn_mask()) but the mask type is still 'none'. The mask loss helper needs an actual mask channel to learn, so the configuration is contradictory. It fails fast at model initialization, before any training begins.","triggerScenarios":"Initializing any train model plugin (e.g. Original, Dlight, Phaze-A) with a config file where loss.learn_mask = True and loss.mask_type = none. Also triggered when penalized_mask_loss validation passes but learn_mask was left enabled from a previous experiment while mask_type was reset.","commonSituations":"User copies an old config file, disables the mask in the GUI, or upgrades Faceswap where config defaults changed; the 'Learn Mask' toggle stays on from a prior training run that used a mask.","solutions":["Set a mask_type in the model's config (e.g. components, extended, dfl_full, dfl_x_hybrid) via the GUI config editor or by editing <model_dir>/<plugin>_config.json","Or set loss.learn_mask = False in the same config file if you do not want the mask included in the loss","Re-run training; the error is raised in __init__ so no restart cleanup is needed"],"exampleFix":"# before (in <model>_config.json)\n\"loss\": {\"learn_mask\": true, \"mask_type\": \"none\", ...}\n\n# after - option 1: pick a mask\n\"loss\": {\"learn_mask\": true, \"mask_type\": \"components\", ...}\n# after - option 2: disable learn mask\n\"loss\": {\"learn_mask\": false, \"mask_type\": \"none\", ...}","handlingStrategy":"validation","validationCode":"from lib.config import Config as FSConfig  # or however cfg is loaded\ncfg.load_config(config_file=path)\nif cfg.Loss.learn_mask() and cfg.Loss.mask_type() == \"none\":\n    raise SystemExit(\"Set loss.mask_type or disable loss.learn_mask before training\")","typeGuard":null,"tryCatchPattern":"try:\n    model = MyModel(model_dir, args)\nexcept FaceswapError as err:\n    if \"Learn Mask\" in str(err):\n        # fix config programmatically and retry once\n        patch_config(mask_type=\"components\")\n        model = MyModel(model_dir, args)\n    else:\n        raise","preventionTips":["When toggling mask options in the GUI, always re-check that mask_type is set whenever learn_mask or penalized_mask_loss is enabled","Keep per-experiment config files so mask settings never leak between runs"],"tags":["faceswap","config","training","mask","validation"],"backgroundTag":null,"analyzedSha":"f530cb7508ae670f6474f8a7d9c4df94705cf96b","analyzedAt":"2026-08-15T02:59:26.626Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}