From 31e7ca5af040bc7c274bb131cd620ae64696c205 Mon Sep 17 00:00:00 2001 From: Holden Date: Fri, 12 Jun 2026 15:58:29 +0000 Subject: [PATCH] fix: Frigate face count API structure and Immich 401 error message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Frigate /api/faces response has person names as top-level keys with lists of filenames — {person: [file, ...], "train": [...]}. The old code incorrectly looked inside data["train"] as if it were a dict of persons, causing 'list object has no attribute items' on every run. Immich get_people() now checks for 401 before raise_for_status() and logs a clear "API key invalid or expired" message instead of the raw requests exception string. Co-Authored-By: Claude Sonnet 4.6 --- winnow/frigate_api.py | 9 +++++++-- winnow/immich_api.py | 5 ++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/winnow/frigate_api.py b/winnow/frigate_api.py index 4409f05..1988bb4 100644 --- a/winnow/frigate_api.py +++ b/winnow/frigate_api.py @@ -21,8 +21,13 @@ def get_frigate_face_counts() -> dict[str, int] | None: resp = requests.get(f"{frigate_url}/api/faces", timeout=10) resp.raise_for_status() data = resp.json() - train = data.get("train", {}) - return {name: len(files) for name, files in train.items() if isinstance(files, list)} + # Response: {person_name: [file, ...], "train": [...], ...} + # "train" is a flat pending list, not a person — skip it. + return { + name: len(files) + for name, files in data.items() + if name != "train" and isinstance(files, list) + } except Exception as e: logger.warning(f"Could not query Frigate face counts: {e}") return None diff --git a/winnow/immich_api.py b/winnow/immich_api.py index b12a66b..4e87be6 100644 --- a/winnow/immich_api.py +++ b/winnow/immich_api.py @@ -35,10 +35,13 @@ def get_people() -> list[dict]: headers=get_headers(), timeout=10, ) + if resp.status_code == 401: + logger.error("Immich API key is invalid or expired (401 Unauthorized). Update API_KEY.") + return [] resp.raise_for_status() return resp.json().get("people", []) except (requests.RequestException, ValueError) as e: - logger.error(f"Failed to fetch people: {e}") + logger.error(f"Failed to fetch people from Immich: {e}") return []