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

  1. Use the exact topic names registered in the subscription manager (expose a list-topics call/endpoint for clients)
  2. Normalize input before subscribing: topic.strip() (and case-fold if the registry does)
  3. Register new topics in the manager's init before clients subscribe to them
  4. 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

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


AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16). Data as JSON: /api/errors/d0056fd2cba0a808. Report an issue: GitHub.