{"record":{"id":"7c55f77a76eb07a7","repo":"deepfakes/faceswap","slug":"penalized-mask-loss-has-been-selected-but-you-have","errorCode":null,"errorMessage":"Penalized Mask Loss has been selected but you have not chosen a Mask to use. Please select a mask or disable Penalized Mask Loss.","messagePattern":"Penalized Mask Loss has been selected but you have not chosen a Mask to use\\. Please select a mask or disable Penalized Mask Loss\\.","errorType":"exception","errorClass":"FaceswapError","httpStatus":null,"severity":"error","filePath":"plugins/train/model/_base/model.py","lineNumber":67,"sourceCode":"        logger.debug(parse_class_init(locals()))\n        # Input shape must be set within the plugin after initializing\n        self.input_shape: tuple[int, ...] = ()\n        \"\"\"A `tuple` of `ints` defining the shape of the faces that the model takes as input. This\n        should be overridden by model plugins in their :func:`__init__` function. If the input size\n        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,","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/deepfakes/faceswap/blob/f530cb7508ae670f6474f8a7d9c4df94705cf96b/plugins/train/model/_base/model.py#L49-L85","documentation":"Constructor-time validation in the training ModelBase: the config has penalized_mask_loss enabled but mask_type is 'none'. Penalized mask loss applies a penalty outside a mask, so it is meaningless without one; Faceswap refuses to start training rather than silently training without the penalty.","triggerScenarios":"Creating/initiating a training session where cfg.Loss.penalized_mask_loss() is True and cfg.Loss.mask_type() == 'none' in the model's training configuration.","commonSituations":"User disables the mask (to save VRAM or simplify) but forgets they earlier enabled penalized mask loss; hand-editing the loss section of the config; toggling settings independently in the GUI.","solutions":["Set Mask > mask_type in the training config to an actual mask that exists for your faces (see also error 40).","Or disable Loss > penalized_mask_loss if you want to train without masks.","Use the GUI config editor, which makes the incompatible combination visible when reviewing settings."],"exampleFix":"# before (training config)\nmask_type = none\npenalized_mask_loss = True\n\n# after\nmask_type = vgg-clear\npenalized_mask_loss = True\n# or: penalized_mask_loss = False with mask_type = none","handlingStrategy":"validation","validationCode":"from lib.config import cfg\ncfg.load_config(config_file=arguments.config_file)\nassert not (cfg.Loss.penalized_mask_loss() and cfg.Loss.mask_type() == \"none\"), \\\n    \"penalized_mask_loss requires a mask_type\"","typeGuard":"def mask_loss_config_valid(penalized: bool, mask_type: str) -> bool:\n    return not (penalized and mask_type == \"none\")","tryCatchPattern":null,"preventionTips":["Whenever you set mask_type to 'none', sweep the loss section for mask-dependent options (penalized_mask_loss, learn_mask) and disable them.","Review the whole loss/mask block together in the GUI config editor instead of toggling single options."],"tags":["faceswap","training","mask","configuration","validation"],"backgroundTag":null,"analyzedSha":"f530cb7508ae670f6474f8a7d9c4df94705cf96b","analyzedAt":"2026-08-15T02:59:26.626Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}