{"record":{"id":"406f10b7c06df6d4","repo":"ruvnet/RuView","slug":"failed-to-create-stream-response-status","errorCode":null,"errorMessage":"Failed to create stream: {response.status}","messagePattern":"Failed to create stream: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"plans/phase2-architecture/api-architecture.md","lineNumber":1413,"sourceCode":"                f\"{self.base_url}/streams\",\n                headers=headers,\n                json=payload\n            ) as response:\n                if response.status == 201:\n                    stream_data = await response.json()\n                    stream_id = stream_data['id']\n                    rtmp_url = stream_data['ingests']['rtmp']['url']\n                    stream_key = stream_data['ingests']['rtmp']['stream_key']\n                    \n                    self.active_streams[stream_id] = {\n                        'rtmp_url': rtmp_url,\n                        'stream_key': stream_key,\n                        'status': 'created'\n                    }\n                    \n                    return stream_id, f\"{rtmp_url}/{stream_key}\"\n                else:\n                    raise Exception(f\"Failed to create stream: {response.status}\")\n    \n    async def start_pose_visualization_stream(self, stream_id: str):\n        \"\"\"Start streaming pose visualization\"\"\"\n        if stream_id not in self.active_streams:\n            raise ValueError(f\"Unknown stream: {stream_id}\")\n        \n        stream_info = self.active_streams[stream_id]\n        rtmp_endpoint = f\"{stream_info['rtmp_url']}/{stream_info['stream_key']}\"\n        \n        # Start FFmpeg process for streaming\n        ffmpeg_cmd = [\n            'ffmpeg',\n            '-f', 'rawvideo',\n            '-pixel_format', 'bgr24',\n            '-video_size', '1280x720',\n            '-framerate', '30',\n            '-i', '-',  # Input from stdin\n            '-c:v', 'libx264',","sourceCodeStart":1395,"sourceCodeEnd":1431,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/plans/phase2-architecture/api-architecture.md#L1395-L1431","documentation":"Spec code in plans/phase2-architecture/api-architecture.md: the streaming provider adapter (RestStreamIO-style) creates a broadcast over HTTP and, when the response status is not the expected success code, raises a generic Exception('Failed to create stream: {status}'). Only the numeric status surfaces — the provider's response body with the actual reason (auth failure, quota, invalid name) is never read, making diagnosis harder.","triggerScenarios":"POSTing the create-stream request with invalid/expired provider credentials (401/403), exhausted quota or plan limits (4xx), provider outage (5xx), egress blocked by firewall, or a 2xx code the code does not expect (e.g. 200 vs 201) which is treated as failure.","commonSituations":"Expired streaming API key; wrong provider region/base URL; corporate network blocking RTMP/API egress; provider changed its success status or response schema.","solutions":["Log/read the provider response body before raising — the status alone rarely explains 4xx rejections","Verify provider credentials and that the base URL/region match the account","Accept all 2xx codes (resp.status // 100 == 2), not just one expected code","Retry with backoff on 5xx/timeouts; fail fast on 4xx after reading the body"],"exampleFix":"# before\nelse:\n    raise Exception(f\"Failed to create stream: {response.status}\")  # reason discarded\n\n# after\nelse:\n    body = await response.text()\n    logger.error(\"stream create failed: %s %s\", response.status, body[:500])\n    raise Exception(f\"Failed to create stream: {response.status}: {body[:200]}\")","handlingStrategy":"retry","validationCode":"# Pre-flight the provider before starting a session\nasync def provider_ready(client) -> bool:\n    resp = await client.get(\"/api/streams\")  # cheap authenticated call\n    return resp.status == 200  # credentials + reachability OK","typeGuard":null,"tryCatchPattern":"for attempt in range(3):\n    try:\n        stream_id, url = await provider.create_stream(name)\n        break\n    except Exception as e:  # message carries the provider status code\n        if \"500\" in str(e) or \"timeout\" in str(e).lower():\n            await asyncio.sleep(2 ** attempt)\n            continue\n        raise  # 4xx will not heal — fix credentials/quota first","preventionTips":["Read and log the provider response body when implementing this adapter — the bare status code is not diagnosable","Accept any 2xx as success so provider-side changes (201 -> 200) do not break stream creation","Keep credentials and region/base URL in config and validate them with a cheap API call at startup"],"tags":["streaming","rtmp","http","external-api","error-handling","python","spec"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}