HKUDS/Vibe-Trading · error · FileNotFoundError
Media file not found: {media_path}
Error message
Media file not found: {media_path} What it means
_send_media_file verifies the media path with Path.is_file() before upload and raises FileNotFoundError if it does not exist. The media pipeline (AES-encrypt + CDN upload) requires the raw bytes, so a missing file fails fast before any network calls.
Source
Thrown at agent/src/channels/weixin.py:1342
async def _send_media_file(
self,
to_user_id: str,
media_path: str,
context_token: str,
) -> None:
"""Upload a local file to WeChat CDN and send it as a media message.
Follows the exact protocol from ``@tencent-weixin/openclaw-weixin`` v1.0.3:
1. Generate a random 16-byte AES key (client-side).
2. Call ``getuploadurl`` with file metadata + hex-encoded AES key.
3. AES-128-ECB encrypt the file and POST to CDN (``{cdnBaseUrl}/upload``).
4. Read ``x-encrypted-param`` header from CDN response as the download param.
5. Send a ``sendmessage`` with the appropriate media item referencing the upload.
"""
p = Path(media_path)
if not p.is_file():
raise FileNotFoundError(f"Media file not found: {media_path}")
raw_data = p.read_bytes()
raw_size = len(raw_data)
raw_md5 = hashlib.md5(raw_data).hexdigest()
# Determine upload media type from extension
ext = p.suffix.lower()
if ext in _IMAGE_EXTS:
upload_type = UPLOAD_MEDIA_IMAGE
item_type = ITEM_IMAGE
item_key = "image_item"
elif ext in _VIDEO_EXTS:
upload_type = UPLOAD_MEDIA_VIDEO
item_type = ITEM_VIDEO
item_key = "video_item"
elif ext in _VOICE_EXTS:
upload_type = UPLOAD_MEDIA_VOICE
item_type = ITEM_VOICEView on GitHub (pinned to 80ffdda44c)
Solutions
- Verify the file exists (and capture its bytes) before queuing the send.
- Generate media into a stable directory you control and pass an absolute path.
- Keep the temp file alive until the send completes (close only after awaiting send).
- Check mounts/permissions if running in a container.
Example fix
// before
await channel.send_media(chat_id, media_path=tmp_path)
# after
p = Path(tmp_path).resolve()
if not p.is_file():
raise FileNotFoundError(tmp_path)
await channel.send_media(chat_id, str(p)) Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def media_ok(path: str) -> bool:
p = Path(path)
return p.is_file() and p.stat().st_size > 0 Type guard
from pathlib import Path
def is_sendable_media(path: str) -> bool:
p = Path(path)
return p.is_file() and not p.is_dir() Try / catch
try:
await channel.send_media(chat_id, path)
except FileNotFoundError as e:
if "Media file not found" in str(e):
regenerate_or_skip(path)
else:
raise Prevention
- Use absolute paths for generated media.
- Keep temp files alive until send completes.
- Validate existence right before the send call.
When it happens
Trigger: Calling send() with a media attachment whose media_path does not exist or is a directory — e.g. temp file already cleaned up, wrong path, file deleted between generation and send.
Common situations: Tempfile garbage collection (cleanup handlers, NamedTemporaryFile context exit) deleting the media before send; agent-generated artifacts written to a different working directory; path built with a stale filename; container filesystem where the mount is missing.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- getuploadurl returned no upload URL (need upload_full_url or
- WeChat send media error (ret={ret}, errcode={errcode}): {dat
- unknown sort {v!r}; expected one of {sorted(_VALID_SORTS)}
- unknown zoo {zoo!r}; expected one of {sorted(_VALID_ZOOS)}
- {str(e)}
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/2fbacdccac410d21.
Report an issue: GitHub.