{"record":{"id":"f51c3be1e4c3c1e2","repo":"ruvnet/RuView","slug":"cannot-get-connection-stats-for-reconnection","errorCode":null,"errorMessage":"Cannot get connection stats for reconnection","messagePattern":"Cannot get connection stats for reconnection","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ui/services/pose.service.js","lineNumber":715,"sourceCode":"        error: error.message,\n        connectionState: this.connectionState,\n        lastUpdate: this.performanceMetrics.lastUpdateTime\n      };\n    }\n  }\n\n  // Force reconnection\n  async reconnectStream() {\n    if (!this.streamConnection) {\n      throw new Error('No active stream connection to reconnect');\n    }\n\n    this.logger.info('Forcing stream reconnection');\n    \n    // Get current connection stats to preserve options\n    const stats = wsService.getConnectionStats(this.streamConnection);\n    if (!stats) {\n      throw new Error('Cannot get connection stats for reconnection');\n    }\n\n    // Extract original options from URL parameters\n    const url = new URL(stats.url);\n    const params = Object.fromEntries(url.searchParams);\n    \n    const options = {\n      zoneIds: params.zone_ids ? params.zone_ids.split(',') : undefined,\n      minConfidence: params.min_confidence ? parseFloat(params.min_confidence) : undefined,\n      maxFps: params.max_fps ? parseInt(params.max_fps) : undefined,\n      token: params.token\n    };\n\n    // Stop current stream\n    this.stopPoseStream();\n\n    // Start new stream with same options\n    return this.startPoseStream(options);","sourceCodeStart":697,"sourceCodeEnd":733,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/ui/services/pose.service.js#L697-L733","documentation":"Thrown by PoseService.reconnectStream() when wsService.getConnectionStats(this.streamConnection) returns null. getConnectionStats (ui/services/websocket.service.js:588) returns null only when findConnectionById cannot find the id in the WebSocketService connection registry, so this error means the pose service holds a stale handle to a connection that was already closed, purged, or never registered.","triggerScenarios":"Calling reconnectStream() after the underlying WebSocket dropped and WebSocketService removed it from its connections map; calling it after stopPoseStream()/dispose() already tore the connection down; racing the service's own automatic reconnection which closed and re-registered the socket under a new id; module/HMR reload clearing the ws registry while pose.service's singleton survived.","commonSituations":"UI reconnect button clicked after the server closed the socket; double-click on reconnect; dev-time hot reload leaving stale ids; stream stopped by an error handler but streamConnection not cleared.","solutions":["Check the connection still exists before reconnecting: wsService.getActiveConnections().some(c => c.id === this.streamConnection)","Store the original stream options on PoseService inside startPoseStream() and reuse them for reconnect instead of re-parsing them from the connection URL","If the connection is gone, fall back to startPoseStream(lastStreamOptions) instead of throwing","Clear this.streamConnection in stopPoseStream()/dispose() so the earlier 'No active stream connection' guard at line 706 fires instead"],"exampleFix":"// before\nconst stats = wsService.getConnectionStats(this.streamConnection);\nif (!stats) {\n  throw new Error('Cannot get connection stats for reconnection');\n}\nconst url = new URL(stats.url);\n// ...\n\n// after (in startPoseStream): this.lastStreamOptions = options;\nasync reconnectStream() {\n  if (!this.streamConnection) {\n    throw new Error('No active stream connection to reconnect');\n  }\n  const stats = wsService.getConnectionStats(this.streamConnection);\n  if (!stats) {\n    this.logger.warn('Stream connection no longer registered; restarting from stored options');\n    return this.startPoseStream(this.lastStreamOptions);\n  }\n  // ...parse options from stats.url...\n}","handlingStrategy":"validation","validationCode":"// Before calling reconnectStream(), confirm the connection is still registered\nconst isActive = wsService\n  .getActiveConnections()\n  .some((c) => c.id === poseService.streamConnection);\nif (!isActive) {\n  // connection already gone: restart from last-known options instead of reconnecting\n  return poseService.startPoseStream(lastStreamOptions);\n}\nawait poseService.reconnectStream();","typeGuard":"/** True when the stored stream connection id is still live in the WS registry. */\nfunction isLiveConnection(wsService, connectionId) {\n  return Boolean(connectionId) && wsService.getConnectionStats(connectionId) !== null;\n}","tryCatchPattern":null,"preventionTips":["Persist the original stream options at startPoseStream() time instead of recovering them from the connection URL","Clear streamConnection whenever stopPoseStream()/dispose() runs so stale ids never linger","Disable or debounce reconnect UI while an automatic reconnection is in flight"],"tags":["websocket","state-management","ui","stale-handle"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}