deepfakes/faceswap · error · FaceswapError
Landmark based masks cannot be created for {self._landmark_t
Error message
Landmark based masks cannot be created for {self._landmark_type.name} What it means
Raised by MaskAlignmentsFile._get_slices in lib/align/aligned_mask.py when the mask's landmark_type has no entry in the lookup dict for the requested area. For areas 'eye'/'mouth' the lookup is LANDMARK_PARTS (contains only LM_2D_68, LM_2D_98, LM_2D_4); for 'face'/'face_extended' it is LANDMARK_MASK_PARTS (contains only LM_2D_68 and LM_2D_98). Faceswap throws this because it has no slice definitions to build a landmark-based mask for that landmark type/area combination.
Source
Thrown at lib/align/aligned_mask.py:510
def __repr__(self) -> str:
"""Pretty print for logging"""
params = {f"{k[1:]}": format_array(v) if isinstance(v, np.ndarray) else v
for k, v in self.__dict__.items()
if k in ("_area", "_landmark_type", "_landmarks", "_size",
"_dilation", "_blur_kernel", "_blur_type", "blur_passes")}
s_params = ", ".join(f"{k}={repr(v)}" for k, v in params.items())
return f"{self.__class__.__name__}({s_params})"
def _get_slices(self) -> list[slice] | list[list[slice]]:
"""Obtain the slices that will extract the points for the given area and landmark type
Returns
-------
The slices required to extract landmark points for creating a mask
"""
parts = LANDMARK_PARTS if self._area in ("eye", "mouth") else LANDMARK_MASK_PARTS
if self._landmark_type not in parts:
raise FaceswapError(
f"Landmark based masks cannot be created for {self._landmark_type.name}")
lm_parts = parts[self._landmark_type]
mapped = {"mouth": ["mouth_outer"],
"eye": ["right_eye", "left_eye"],
"face": list(lm_parts),
"face_extended": list(lm_parts)}[self._area]
if not all(parts in lm_parts for parts in mapped):
raise FaceswapError(
f"Landmark based masks cannot be created for {self._landmark_type.name}")
if self._area in ("eye", "mouth"):
retval: list[slice] | list[list[slice]] = [slice(*lm_parts[v][:2]) for v in mapped]
else:
retval = [[slice(*p) for p in T.cast(list[tuple[int, int]], lm_parts[v])]
for v in mapped]
logger.trace("[LM_MASK] area: '%s', slices: %s", # type:ignore[attr-defined]View on GitHub (pinned to f530cb7508)
Solutions
- Re-extract or re-detect faces with a detector/detector+2D-68 landmark pipeline (e.g. use the 68-point or 98-point landmark flavor) so landmark_type is LM_2D_68 or LM_2D_98
- For eye/mouth masks, ensure alignments contain at least the eye/mouth landmark indices; switch to a different mask type (e.g. components, extended, dfl) which does not rely on LANDMARK_MASK_PARTS
- Check the alignments file's landmark type with the alignments tool (e.g. 'alignments tool > spatial' or inspect DetectedFace.landmarks) to confirm which LandmarkType was stored
Example fix
# before
mask = MaskAlignmentsFile(area="face",
landmark_type=LandmarkType.LM_2D_4,
landmarks=face.landmarks, # only 4 points
size=128)
# after
# LM_2D_4 has no face-mask slices; use a supported type
mask = MaskAlignmentsFile(area="face",
landmark_type=LandmarkType.LM_2D_68,
landmarks=face.landmarks_68,
size=128) Defensive patterns
Strategy: validation
Validate before calling
from lib.align.constants import LandmarkType, LANDMARK_PARTS, LANDMARK_MASK_PARTS
def can_build_mask(area, lmk_type):
parts = LANDMARK_PARTS if area in ("eye", "mouth") else LANDMARK_MASK_PARTS
return lmk_type in parts Type guard
from lib.align.constants import LandmarkType, LANDMARK_PARTS, LANDMARK_MASK_PARTS
def maskable_landmark_type(area: str, lmk: LandmarkType) -> bool:
"""True if MaskAlignmentsFile supports (area, lmk) combination."""
table = LANDMARK_PARTS if area in ("eye", "mouth") else LANDMARK_MASK_PARTS
return lmk in table Try / catch
try:
mask = MaskAlignmentsFile(area=area, landmark_type=lmk_type, landmarks=lms, size=128)
except FaceswapError:
logger.warning("mask unsupported for %s/%s, skipping", area, lmk_type.name)
mask = None Prevention
- Check LandmarkType against LANDMARK_PARTS/LANDMARK_MASK_PARTS before building masks
- Standardize pipelines on 68- or 98-point landmark extraction
- Fail fast on 4-point alignments before requesting eye/mouth/face landmark masks
When it happens
Trigger: Constructing MaskAlignmentsFile(area=..., landmark_type=..., landmarks=...) where area is 'face' or 'face_extended' and landmark_type is LM_2D_4, LM_2D_51 or LM_3D_26; or area is 'eye'/'mouth' with landmark_type LM_2D_51 or LM_3D_26. Happens at __init__ time (self.mask = self.generate_mask()).
Common situations: Running the mask plugin 'landmarks' with a detector that outputs 4-point landmarks (e.g. a 68-point pipeline replaced by a 4-point detector) then requesting a face mask; loading old alignments converted to LM_2D_51; requesting extended/face landmark masks after extraction with a minimal landmark set.
Related errors
- Alignments file not found at {self._file}
- Penalized Mask Loss has been selected but you have not chose
- 'Learn Mask' has been selected but you have not chosen a Mas
- No display detected. GUI mode has been disabled.
- Config file does not exist at: {ini_path}
AI-assisted analysis of deepfakes/faceswap@f530cb7508 (2026-08-15).
Data as JSON: /api/errors/c5a85916650865a7.
Report an issue: GitHub.