{"record":{"id":"dc354099d631f66a","repo":"ruvnet/RuView","slug":"an-internal-error-occurred-please-try-again-later-dc3540","errorCode":null,"errorMessage":"An internal error occurred. Please try again later.","messagePattern":"An internal error occurred\\. Please try again later\\.","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"archive/v1/src/api/routers/stream.py","lineNumber":353,"sourceCode":"        # Calculate uptime (simplified for now)\n        uptime_seconds = 0.0\n        if status.get(\"running\", False):\n            uptime_seconds = 3600.0  # Default 1 hour for demo\n        \n        return StreamStatus(\n            is_active=status.get(\"running\", False),\n            connected_clients=connections.get(\"total_clients\", status[\"connections\"][\"active\"]),\n            streams=[{\n                \"type\": \"pose_stream\",\n                \"active\": status.get(\"running\", False),\n                \"buffer_size\": status[\"buffers\"][\"pose_buffer_size\"]\n            }],\n            uptime_seconds=uptime_seconds\n        )\n        \n    except Exception as e:\n        logger.error(f\"Error getting stream status: {e}\")\n        raise HTTPException(\n            status_code=500,\n            detail=\"An internal error occurred. Please try again later.\"\n        )\n\n\n@router.post(\"/start\")\nasync def start_streaming(\n    stream_service: StreamService = Depends(get_stream_service),\n    current_user: Dict = Depends(require_auth)\n):\n    \"\"\"Start the streaming service.\"\"\"\n    try:\n        logger.info(f\"Starting streaming service by user: {current_user['id']}\")\n        \n        if await stream_service.is_active():\n            return JSONResponse(\n                status_code=200,\n                content={\"message\": \"Streaming service is already active\"}","sourceCodeStart":335,"sourceCodeEnd":371,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/archive/v1/src/api/routers/stream.py#L335-L371","documentation":"Catch-all on GET /stream/status in archive/v1/src/api/routers/stream.py. The handler merges stream_service.get_status() with connection_manager.get_connection_stats() and builds a StreamStatus response. A likely failure is built into the response assembly itself: `connections.get(\"total_clients\", status[\"connections\"][\"active\"])` and `status[\"buffers\"][\"pose_buffer_size\"]` use hard bracket lookups, so a status dict missing 'connections' or 'buffers.pose_buffer_size' raises KeyError, which is swallowed and returned as HTTP 500 logged as 'Error getting stream status'. Note this route has no auth dependency.","triggerScenarios":"GET /stream/status when stream_service.get_status() returns a dict without the 'connections' key (so the .get() fallback itself raises KeyError); status lacking 'buffers.pose_buffer_size'; connection_manager.get_connection_stats() raising; StreamStatus model validation failing on the constructed payload.","commonSituations":"Calling status before the streaming service was ever started, so its internal status dict is partially initialized; schema drift between StreamService.get_status() and this router after an upgrade; Pydantic StreamStatus rejecting a field type (e.g., connected_clients=None when connection stats are unavailable).","solutions":["Read the server log line 'Error getting stream status: {e}' — it is usually a KeyError naming the missing key","Confirm stream_service.get_status() returns 'connections' (with 'active') and 'buffers' (with 'pose_buffer_size')","Replace the hard bracket lookups with .get() defaults (e.g., status.get(\"connections\", {}).get(\"active\", 0)) so a sparse status dict degrades gracefully","If StreamStatus validation is the cause, align the response_model fields with what the service actually returns"],"exampleFix":"# before\nconnected_clients=connections.get(\"total_clients\", status[\"connections\"][\"active\"]),\nstreams=[{\"type\": \"pose_stream\", \"active\": status.get(\"running\", False), \"buffer_size\": status[\"buffers\"][\"pose_buffer_size\"]}],\n\n# after\nconnected_clients=connections.get(\"total_clients\", status.get(\"connections\", {}).get(\"active\", 0)),\nstreams=[{\"type\": \"pose_stream\", \"active\": status.get(\"running\", False), \"buffer_size\": status.get(\"buffers\", {}).get(\"pose_buffer_size\", 0)}],","handlingStrategy":"retry","validationCode":"import httpx\n\n# probe the cheaper, dependency-free liveness path before relying on /status\nresp = httpx.get(f\"{API}/stream/status\", timeout=5)\nassert resp.status_code != 500 or retry_once(), \"status assembly failing server-side\"","typeGuard":"def status_response_ok(resp: httpx.Response) -> bool:\n    if resp.status_code != 200:\n        return False\n    body = resp.json()\n    return isinstance(body.get(\"connected_clients\"), int) and isinstance(body.get(\"streams\"), list)","tryCatchPattern":"for attempt in range(2):\n    try:\n        resp = httpx.get(f\"{API}/stream/status\", timeout=5)\n        if resp.status_code == 200:\n            break\n    except httpx.RequestError:\n        continue\nelse:\n    raise RuntimeError(\"stream status unavailable after retry\")","preventionTips":["After upgrading streaming components, hit /stream/status once in a smoke test to catch schema drift early","Do not rely on /stream/status before the service has ever been started; initialize first","Remember /stream/status is unauthenticated — do not expose the API publicly expecting auth on it"],"tags":["fastapi","http-500","streaming","websocket","api","python"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}