{"record":{"id":"a9d46f7cf7ed3f26","repo":"ruvnet/RuView","slug":"invalid-stream-options-validationresult-errors","errorCode":null,"errorMessage":"Invalid stream options: ${validationResult.errors.join(', ')}","messagePattern":"Invalid stream options: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ui/services/pose.service.js","lineNumber":131,"sourceCode":"  // Get pose statistics\n  async getStats(hours = 24) {\n    return apiService.get(API_CONFIG.ENDPOINTS.POSE.STATS, { hours });\n  }\n\n  // Start pose stream\n  async startPoseStream(options = {}) {\n    if (this.streamConnection) {\n      this.logger.warn('Pose stream already active', { connectionId: this.streamConnection });\n      return this.streamConnection;\n    }\n\n    this.logger.info('Starting pose stream', { options });\n    this.resetPerformanceMetrics();\n\n    // Validate options\n    const validationResult = this.validateStreamOptions(options);\n    if (!validationResult.valid) {\n      throw new Error(`Invalid stream options: ${validationResult.errors.join(', ')}`);\n    }\n\n    // Use a lower confidence threshold when model inference is active\n    const defaultThreshold = this.modelActive\n      ? this.config.confidenceThresholdModelInference\n      : this.config.confidenceThreshold;\n\n    const params = {\n      zone_ids: options.zoneIds?.join(','),\n      min_confidence: options.minConfidence || defaultThreshold,\n      max_fps: options.maxFps || 30,\n      token: options.token || apiService.authToken\n    };\n\n    // Remove undefined values\n    Object.keys(params).forEach(key => \n      params[key] === undefined && delete params[key]\n    );","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/ui/services/pose.service.js#L113-L149","documentation":"startPoseStream validates its options via validateStreamOptions (ui/services/pose.service.js:200) and throws one Error joining all violations. The rules: `zoneIds`, if provided, must be an array; `minConfidence` must be a number in [0,1]; `maxFps` must be a number greater than 0 and at most 60. All violations are reported together, comma-separated.","triggerScenarios":"startPoseStream({ zoneIds: 'kitchen' }) (string instead of array); { minConfidence: 75 } (percent instead of 0..1 fraction); { maxFps: 0 } or { maxFps: 120 }; { minConfidence: '0.5' } (string).","commonSituations":"UI sliders emitting 0–100 confidence values; joining zone ids into a comma-separated string before passing; requesting >60 fps for smoother playback when the API caps at 60; string values from URL/form params.","solutions":["Pass fractions for confidence: { minConfidence: 0.75 } not 75.","Pass zone ids as an array: { zoneIds: ['kitchen', 'hall'] } not 'kitchen,hall'.","Clamp fps to the supported range: { maxFps: Math.min(60, Math.max(1, fps)) }."],"exampleFix":"// before\nposeService.startPoseStream({ zoneIds: selectedZones.join(','), minConfidence: 75, maxFps: 120 });\n// after\nposeService.startPoseStream({ zoneIds: selectedZones, minConfidence: 0.75, maxFps: 30 });","handlingStrategy":"validation","validationCode":"const errors = [];\nif (options.zoneIds !== undefined && !Array.isArray(options.zoneIds)) errors.push('zoneIds must be an array');\nif (options.minConfidence !== undefined && (typeof options.minConfidence !== 'number' || options.minConfidence < 0 || options.minConfidence > 1)) errors.push('minConfidence must be 0..1');\nif (options.maxFps !== undefined && (typeof options.maxFps !== 'number' || options.maxFps <= 0 || options.maxFps > 60)) errors.push('maxFps must be 1..60');\nif (errors.length === 0) await poseService.startPoseStream(options);","typeGuard":"function isPoseStreamOptions(o) {\n  return (o.zoneIds === undefined || Array.isArray(o.zoneIds))\n    && (o.minConfidence === undefined || (typeof o.minConfidence === 'number' && o.minConfidence >= 0 && o.minConfidence <= 1))\n    && (o.maxFps === undefined || (typeof o.maxFps === 'number' && o.maxFps > 0 && o.maxFps <= 60));\n}","tryCatchPattern":"try {\n  await poseService.startPoseStream(options);\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Invalid stream options')) {\n    // message lists every violated field; fix them, then retry once\n    throw new Error(`stream options rejected: ${e.message}`);\n  }\n  throw e;\n}","preventionTips":["Reuse poseService.validateStreamOptions(options) before starting the stream.","Keep confidence as a 0..1 fraction everywhere in the UI; convert sliders at the boundary.","Pass zone ids as arrays; never pre-join them into strings."],"tags":["validation","websocket","pose-stream","ui","ranges"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}