From 89da9c782b9513c105d3a9117368620a74c3163a Mon Sep 17 00:00:00 2001 From: Codex Date: Sat, 15 Aug 2026 09:42:46 -0700 Subject: [PATCH] fix(unraid): expose sanitized inference error detail --- .../unraid/tail2-pose-server/app/tail2/main.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/servers/unraid/tail2-pose-server/app/tail2/main.py b/servers/unraid/tail2-pose-server/app/tail2/main.py index 6a25096..b463490 100644 --- a/servers/unraid/tail2-pose-server/app/tail2/main.py +++ b/servers/unraid/tail2-pose-server/app/tail2/main.py @@ -41,6 +41,7 @@ class State: self.inference_fault = False self.ws_source_ok = False self.error_code: str | None = None + self.error_detail: str | None = None self.frame_id = 0 self.messages = 0 self.frames_dropped = 0 @@ -97,7 +98,8 @@ def health(): "last_frame_age_ms": round(age, 3) if age is not None else None, "actual_width": state.width or None, "actual_height": state.height or None}, "models": {"detector_ready": state.models_ready, "pose_ready": state.models_ready}, - "error_code": state.error_code, "uptime_seconds": round(time.monotonic() - state.started, 1)} + "error_code": state.error_code, "error_detail": state.error_detail, + "uptime_seconds": round(time.monotonic() - state.started, 1)} @app.get("/v1/capabilities", dependencies=[Depends(authorized)]) @@ -144,14 +146,16 @@ def inference_worker(loop: asyncio.AbstractEventLoop) -> None: threshold = float(os.getenv("DETECTION_THRESHOLD", ".35")); max_people = int(os.getenv("MAX_PEOPLE", "4")) try: models.load(); state.models_ready = True; LOG.info("official detector and pose checkpoints loaded") - except Exception: - state.inference_fault = True; state.error_code = "MODEL_LOAD_FAILED"; LOG.exception("model loading failed"); return + except Exception as exc: + state.inference_fault = True; state.error_code = "MODEL_LOAD_FAILED" + state.error_detail = f"{type(exc).__name__}: {str(exc)[:240]}"; LOG.exception("model loading failed"); return while True: frame = frames.get(); started_ns = time.time_ns(); perf = time.perf_counter_ns() try: people, det_ms, pose_ms = models.infer(frame.pixels, threshold, max_people) finished_ns = time.time_ns(); total_ms = (time.perf_counter_ns() - perf) / 1e6 - state.frame_id += 1; state.cuda_inference_ok = True; state.inference_fault = False; state.error_code = None + state.frame_id += 1; state.cuda_inference_ok = True; state.inference_fault = False + state.error_code = None; state.error_detail = None msg = {"schema": "tail2.pose.v1", "stream_id": config["stream_id"], "session_id": state.session_id, "frame_id": state.frame_id, "source_received_unix_ns": frame.received_ns, "inference_started_unix_ns": started_ns, "inference_finished_unix_ns": finished_ns, @@ -164,8 +168,9 @@ def inference_worker(loop: asyncio.AbstractEventLoop) -> None: "error": None} state.inference_ms.append(total_ms); state.messages += 1; state.ws_source_ok = True hub.publish_on_loop(loop, msg) - except Exception: - state.inference_fault = True; state.error_code = "INFERENCE_FAILED"; LOG.exception("inference failed") + except Exception as exc: + state.inference_fault = True; state.error_code = "INFERENCE_FAILED" + state.error_detail = f"{type(exc).__name__}: {str(exc)[:240]}"; LOG.exception("inference failed") @app.on_event("startup") @@ -178,4 +183,3 @@ async def startup() -> None: if __name__ == "__main__": uvicorn.run(app, host=os.getenv("API_BIND", "0.0.0.0"), port=int(os.getenv("API_PORT", "18120")), access_log=False, ws_max_size=65536) -