ruvnet/RuView · error · HTTPException
Unknown service: {service_name}
Error message
Unknown service: {service_name} What it means
check_service_health raises 400 'Unknown service: {service_name}' when the name it receives is not one of the three hardcoded names mapped to app.state attributes: 'pose' (pose_service), 'stream' (stream_service), or 'hardware' (hardware_service). It is a client-side input error, not a server health problem.
Source
Thrown at archive/v1/src/api/dependencies.py:266
return router_id
# Service health dependencies
async def check_service_health(
request: Request,
service_name: str
) -> bool:
"""Check if a service is healthy."""
try:
if service_name == "pose":
service = getattr(request.app.state, 'pose_service', None)
elif service_name == "stream":
service = getattr(request.app.state, 'stream_service', None)
elif service_name == "hardware":
service = getattr(request.app.state, 'hardware_service', None)
else:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Unknown service: {service_name}"
)
if not service:
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail=f"Service '{service_name}' not available"
)
# Check service health
status_info = await service.get_status()
if status_info.get("status") != "healthy":
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail=f"Service '{service_name}' is unhealthy: {status_info.get('error', 'Unknown error')}"
)
View on GitHub (pinned to 4685618388)
Solutions
- Use exactly one of: pose, stream, hardware
- When adding a new service, extend the chain (or replace it with a dict registry name -> app.state attribute)
- Validate the parameter client-side before calling
Example fix
# before
if service_name == 'pose':
service = getattr(request.app.state, 'pose_service', None)
elif ...
else:
raise HTTPException(400, f'Unknown service: {service_name}')
# after: registry, so new services need one line
SERVICE_ATTRS = {'pose': 'pose_service', 'stream': 'stream_service', 'hardware': 'hardware_service'}
attr = SERVICE_ATTRS.get(service_name)
if attr is None:
raise HTTPException(status_code=400, detail=f'Unknown service: {service_name}')
service = getattr(request.app.state, attr, None) Defensive patterns
Strategy: type-guard
Type guard
KNOWN_SERVICES = frozenset({'pose', 'stream', 'hardware'})
def is_known_service(name: str) -> bool:
"""True when name is one of the services check_service_health maps to app.state."""
return name in KNOWN_SERVICES
# guard before the call
if not is_known_service(service_name):
raise ValueError(f'service must be one of {sorted(KNOWN_SERVICES)}, got {service_name!r}') Try / catch
try:
r = client.get(f'/api/health/{service_name}')
r.raise_for_status()
except httpx.HTTPStatusError as e:
if e.response.status_code == 400:
# unknown name: fix the caller's vocabulary, do not retry
raise ValueError(f'Unsupported service name: {service_name}') from e
raise Prevention
- Define service names as constants shared between client and server
- Extend the check_service_health registry whenever a new service is added to app.state
- Treat 400 here as a programming error, not a runtime failure
When it happens
Trigger: Calling the health dependency/route with service_name like 'inference', 'model', 'api', or a typo such as 'pose '; adding a new service to app.state without extending the if/elif chain in this function.
Common situations: Client and server disagreeing on service names; copy-pasted route parameters; new services registered at startup but forgotten in the health checker.
Related errors
- Page must be >= 1
- Size must be >= 1
- Size must be <= {max_size}
- min_confidence must be between 0.0 and 1.0
- Health check failed: {str(e)}
AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16).
Data as JSON: /api/errors/dacd44e7a0b79244.
Report an issue: GitHub.