ruvnet/RuView · warning · ValueError
Unknown topic: {topic}
Error message
Unknown topic: {topic} What it means
Spec code in plans/phase2-architecture/api-architecture.md: the subscription manager's subscribe(client_id, topic, filters) raises ValueError('Unknown topic: ...') when topic is not a key in self.subscriptions. The registry of valid topics is fixed at init; subscribing does not create topics, so only pre-registered names are accepted.
Source
Thrown at plans/phase2-architecture/api-architecture.md:489
}, client_id)
def disconnect(self, client_id: str):
"""Remove WebSocket connection"""
if client_id in self.active_connections:
del self.active_connections[client_id]
# Remove from all subscriptions
for topic in self.subscriptions:
self.subscriptions[topic].discard(client_id)
# Clean up client info
if client_id in self.client_info:
del self.client_info[client_id]
async def subscribe(self, client_id: str, topic: str, filters: dict = None):
"""Subscribe client to topic"""
if topic not in self.subscriptions:
raise ValueError(f"Unknown topic: {topic}")
self.subscriptions[topic].add(client_id)
self.client_info[client_id]['subscriptions'].add(topic)
# Store filters if provided
if filters:
if 'filters' not in self.client_info[client_id]:
self.client_info[client_id]['filters'] = {}
self.client_info[client_id]['filters'][topic] = filters
# Send confirmation
await self.send_personal_message({
'type': 'subscription',
'topic': topic,
'status': 'subscribed',
'filters': filters
}, client_id)
View on GitHub (pinned to 4685618388)
Solutions
- Use the exact topic names registered in the subscription manager (expose a list-topics call/endpoint for clients)
- Normalize input before subscribing: topic.strip() (and case-fold if the registry does)
- Register new topics in the manager's init before clients subscribe to them
- Catch the ValueError at the WebSocket boundary and send a client-friendly error with the valid topic list
Example fix
# before
await manager.subscribe(client_id, "poses/live") # ValueError: Unknown topic
# after
if topic not in manager.subscriptions:
await send_json(ws, {"error": "unknown topic", "valid": sorted(manager.subscriptions)})
else:
await manager.subscribe(client_id, topic) Defensive patterns
Strategy: validation
Validate before calling
topic = topic.strip()
if topic not in manager.subscriptions:
await ws.send_json({"error": "unknown topic", "valid_topics": sorted(manager.subscriptions)})
return
await manager.subscribe(client_id, topic) Type guard
def is_known_topic(manager, topic: object) -> bool:
return isinstance(topic, str) and topic in manager.subscriptions Try / catch
try:
await manager.subscribe(client_id, topic)
except ValueError as e:
await ws.send_json({"error": str(e), "valid_topics": sorted(manager.subscriptions)}) Prevention
- Publish the valid topic list to clients (docs endpoint or connection handshake) so they never guess
- Normalize topic strings (strip whitespace) before subscribing
- Treat unknown-topic ValueErrors as client input errors (send a helpful message), not server crashes
When it happens
Trigger: A WebSocket client subscribing with a typo'd or unregistered topic name (e.g. 'poses/live' when the registry has 'pose.live'); topic strings taken from user input without validation; a topic added server-side but the client using an older name.
Common situations: Client/server topic vocabulary drift after a deploy; copy-paste of topic names from docs that renamed them; missing strip/lower normalization so 'pose.live ' fails.
Related errors
- Unsupported API version: {version}
- An internal error occurred. Please try again later.
- Invalid stream options: ${validationResult.errors.join(', ')
- Page must be >= 1
- Size must be >= 1
AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16).
Data as JSON: /api/errors/d0056fd2cba0a808.
Report an issue: GitHub.