calesthio/OpenMontage · error · ValueError

Cannot select face without face_id/id: {face}

Error message

Cannot select face without face_id/id: {face}

What it means

Raised by KlingLipSyncTool._face_to_choice when the tool tries to convert a face record from identify_face into a selection choice but the record has neither face_id nor id. This happens on the automatic paths: exactly one detected face, or auto_select_face=True picking the largest face. The tool cannot tell Kling which face to animate without an identifier.

Source

Thrown at tools/avatar/kling_lip_sync.py:453

        if not inputs.get("auto_select_face"):
            return [], {
                "selection_method": "requires_user_selection",
                "selection_reason": "Multiple faces detected and auto_select_face was not enabled",
                "face_count": len(faces),
            }
        selected = max(faces, key=self._face_area)
        choice = [self._face_to_choice(selected)]
        return choice, {
            "selection_method": "auto_selected",
            "selection_reason": "auto_select_face=True selected the largest detected face area",
            "selected_face": choice,
        }

    @staticmethod
    def _face_to_choice(face: dict[str, Any]) -> dict[str, Any]:
        face_id = face.get("face_id") or face.get("id")
        if not face_id:
            raise ValueError(f"Cannot select face without face_id/id: {face}")
        return {"face_id": str(face_id)}

    @staticmethod
    def _face_area(face: dict[str, Any]) -> float:
        for key in ("bbox", "box"):
            value = face.get(key)
            if isinstance(value, list) and len(value) >= 4:
                third = float(value[2])
                fourth = float(value[3])
                width_height_area = max(third, 0.0) * max(fourth, 0.0)
                corner_width = third - float(value[0])
                corner_height = fourth - float(value[1])
                corner_area = (
                    corner_width * corner_height
                    if corner_width > 0 and corner_height > 0
                    else 0.0
                )
                if corner_area and width_height_area:

View on GitHub (pinned to 95e1c3d0ab)

Solutions

  1. Inspect the identify_face output for your video and pass explicit face_choose entries using whatever id field it actually returns, if any
  2. Re-run identify_face; if its schema truly lacks ids, this is a tool bug — report it with the raw face payload
  3. If mocking in tests, include face_id (or id) in every face record

Example fix

# before (mock faces without ids)
faces = [{"bbox": [10, 10, 100, 100]}]

# after
faces = [{"face_id": "face_1", "bbox": [10, 10, 100, 100]}]
Defensive patterns

Strategy: validation

Validate before calling

faces = identify_face(video_id=vid)["faces"]
if not all(f.get("face_id") or f.get("id") for f in faces):
    raise ValueError(f"identify_face returned id-less records: {faces}")
# safe to proceed with auto_select_face or single-face shortcut

Type guard

def faces_have_ids(faces) -> bool:
    return all(bool(f.get("face_id") or f.get("id")) for f in faces)

Prevention

When it happens

Trigger: Running kling_lip_sync on a video where identify_face returns face records whose id field is named something else (e.g. "faceid", "uuid") or is missing entirely. Triggered either via the single-face shortcut or via auto_select_face=True with multiple faces.

Common situations: A changed or unexpected identify_face response schema (upstream API version change), or a hand-crafted faces list passed in tests/mocks that omits the id key.

Related errors


AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15). Data as JSON: /api/errors/aefd09ffb9855368. Report an issue: GitHub.