{"record":{"id":"39eb364db8682381","repo":"ruvnet/RuView","slug":"service-service-name-health-check-failed","errorCode":null,"errorMessage":"Service '{service_name}' health check failed","messagePattern":"Service '(.+?)' health check failed","errorType":"http","errorClass":"HTTPException","httpStatus":503,"severity":"error","filePath":"archive/v1/src/api/dependencies.py","lineNumber":291,"sourceCode":"                status_code=status.HTTP_503_SERVICE_UNAVAILABLE,\n                detail=f\"Service '{service_name}' not available\"\n            )\n        \n        # Check service health\n        status_info = await service.get_status()\n        if status_info.get(\"status\") != \"healthy\":\n            raise HTTPException(\n                status_code=status.HTTP_503_SERVICE_UNAVAILABLE,\n                detail=f\"Service '{service_name}' is unhealthy: {status_info.get('error', 'Unknown error')}\"\n            )\n        \n        return True\n        \n    except HTTPException:\n        raise\n    except Exception as e:\n        logger.error(f\"Error checking service health for {service_name}: {e}\")\n        raise HTTPException(\n            status_code=status.HTTP_503_SERVICE_UNAVAILABLE,\n            detail=f\"Service '{service_name}' health check failed\"\n        )\n\n\n# Rate limiting dependencies\nasync def check_rate_limit(\n    request: Request,\n    current_user: Optional[Dict[str, Any]] = Depends(get_current_user)\n) -> bool:\n    \"\"\"Check rate limiting status.\"\"\"\n    settings = get_settings()\n    \n    # Skip if rate limiting is disabled\n    if not settings.enable_rate_limiting:\n        return True\n    \n    # Rate limiting is handled by middleware","sourceCodeStart":273,"sourceCodeEnd":309,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/archive/v1/src/api/dependencies.py#L273-L309","documentation":"check_service_health raises 503 \"Service '<name>' health check failed\" from the generic except handler when calling service.get_status() itself raises an unexpected exception (as opposed to returning an unhealthy dict). The original exception is logged via logger.error before the 503 is raised, so the log holds the real cause.","triggerScenarios":"get_status() throwing because a dependency client is in a broken state (connection closed, None where an object is expected), a bug in the service's status code path, or an async operation failing mid-probe.","commonSituations":"Service crashed internally but app.state still holds the dead object; status code paths untested against missing optional dependencies; race between service shutdown and a health probe.","solutions":["Grep the API server logs for 'Error checking service health for <name>' — the logged exception is the true cause","Fix or restart the failing service so get_status() completes again","Harden get_status() implementations to report degraded status instead of raising","Retry the health check after remediation; treat 503 as transient"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    r = client.get(f'/api/health/{service_name}')\n    r.raise_for_status()\nexcept httpx.HTTPStatusError as e:\n    if e.response.status_code == 503 and 'health check failed' in e.response.json().get('detail', ''):\n        # get_status() raised: transient broken state, retry with backoff;\n        # the server log line 'Error checking service health for ...' has the cause\n        await asyncio.sleep(backoff)\n        r = client.get(f'/api/health/{service_name}')\n    raise","preventionTips":["Correlate client 503s with the server log's 'Error checking service health' entries","Make get_status() implementations return degraded status instead of raising","Use bounded retries with exponential backoff; escalate if the failure persists"],"tags":["health-check","http-503","error-handling","python"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}