{"record":{"id":"eef30e6fda703ccc","repo":"HKUDS/Vibe-Trading","slug":"cdn-upload-response-missing-x-encrypted-param-head","errorCode":null,"errorMessage":"CDN upload response missing x-encrypted-param header; status={cdn_resp.status_code} headers={dict(cdn_resp.headers)}","messagePattern":"CDN upload response missing x-encrypted-param header; status=(.+?) headers=(.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"agent/src/channels/weixin.py","lineNumber":1422,"sourceCode":"            cdn_upload_url = upload_full_url\n        else:\n            cdn_upload_url = (\n                f\"{self.config.cdn_base_url}/upload\"\n                f\"?encrypted_query_param={quote(upload_param)}\"\n                f\"&filekey={quote(file_key)}\"\n            )\n\n        cdn_resp = await self._client.post(\n            cdn_upload_url,\n            content=encrypted_data,\n            headers={\"Content-Type\": \"application/octet-stream\"},\n        )\n        cdn_resp.raise_for_status()\n\n        # The download encrypted_query_param comes from CDN response header\n        download_param = cdn_resp.headers.get(\"x-encrypted-param\", \"\")\n        if not download_param:\n            raise RuntimeError(\n                \"CDN upload response missing x-encrypted-param header; \"\n                f\"status={cdn_resp.status_code} headers={dict(cdn_resp.headers)}\"\n            )\n\n        # Step 3: Send message with the media item\n        # aes_key for CDNMedia is the hex key encoded as base64\n        # (matches: Buffer.from(uploaded.aeskey).toString(\"base64\"))\n        cdn_aes_key_b64 = base64.b64encode(aes_key_hex.encode()).decode()\n\n        media_item: dict[str, Any] = {\n            \"media\": {\n                \"encrypt_query_param\": download_param,\n                \"aes_key\": cdn_aes_key_b64,\n                \"encrypt_type\": 1,\n            },\n        }\n\n        if item_type == ITEM_IMAGE:","sourceCodeStart":1404,"sourceCodeEnd":1440,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/channels/weixin.py#L1404-L1440","documentation":"After POSTing the AES-encrypted file to the CDN, the channel reads the x-encrypted-param response header, which becomes the download param embedded in the final message. If the header is missing, it raises RuntimeError with the CDN status code and all response headers, because recipients would be unable to download the media without it.","triggerScenarios":"CDN upload returns 2xx (raise_for_status passed) but without an x-encrypted-param header — e.g. proxy/CDN stripping custom headers, a gateway error page returning 200, or a server-side upload that silently failed.","commonSituations":"Corporate proxies or middleboxes dropping unknown x-* headers; regional CDN nodes with different behavior; response actually being an HTML error body with 200 status; partial upload where the CDN stored nothing.","solutions":["Inspect status and headers in the message: if content-type is text/html, the request hit a gateway, not the CDN — fix routing/base URL.","Bypass or configure proxies to forward x-encrypted-param; test from a different network.","Retry the upload; transient CDN inconsistencies can resolve themselves.","Verify the encrypted payload and content-length were sent intact (compare with a known-good small image upload)."],"exampleFix":"// before\ncdn_resp = await client.post(upload_url, content=encrypted)\ncdn_resp.raise_for_status()\n\n// after\ncdn_resp = await client.post(upload_url, content=encrypted)\ncdn_resp.raise_for_status()\nif \"x-encrypted-param\" not in cdn_resp.headers:\n    self.logger.warning(\"CDN dropped header, retrying; resp={}\", cdn_resp.text[:200])\n    cdn_resp = await client.post(upload_url, content=encrypted)\n    cdn_resp.raise_for_status()","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    await channel.send_media(chat_id, path)\nexcept RuntimeError as e:\n    if \"x-encrypted-param\" in str(e):\n        await asyncio.sleep(5)\n        await channel.send_media(chat_id, path)  # retry CDN upload\n    else:\n        raise","preventionTips":["Ensure proxies/gateways forward x-* response headers.","Verify CDN base URL routing is not intercepted by an HTML gateway.","Retry transient CDN inconsistencies with a small backoff."],"tags":["wechat","cdn-upload","missing-header","media"],"backgroundTag":"missing-response-header","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}