OpenBMB/ChatDev · error · FileNotFoundError
Attachment source not found: {source}
Error message
Attachment source not found: {source} What it means
AttachmentManager.register_file raises plain FileNotFoundError when the local path passed in does not exist on disk — checked before any MIME guessing, hashing, or persistence. It is a pre-registration sanity check, not a download failure.
Source
Thrown at utils/attachments.py:89
def register_file(
self,
file_path: Path | str,
*,
kind: MessageBlockType = MessageBlockType.FILE,
display_name: Optional[str] = None,
mime_type: Optional[str] = None,
attachment_id: Optional[str] = None,
copy_file: bool = True,
description: Optional[str] = None,
extra: Optional[Dict[str, Any]] = None,
persist: bool = True,
deduplicate: bool = False,
) -> AttachmentRecord:
"""Register a local file and return its attachment record."""
source = Path(file_path)
if not source.exists():
raise FileNotFoundError(f"Attachment source not found: {source}")
guessed_mime = mime_type or (mimetypes.guess_type(source.name)[0] or "application/octet-stream")
attachment_id = attachment_id or uuid.uuid4().hex
sha256_source = _sha256_file(source)
if deduplicate:
existing = self._find_duplicate_by_hash(
sha256_source,
copy_file=copy_file,
source_path=source,
)
if existing:
return existing
if copy_file:
target_dir = self.root / attachment_id
target_dir.mkdir(parents=True, exist_ok=True)
target_path = target_dir / source.name
shutil.copy2(source, target_path)View on GitHub (pinned to 4fb2db0ea9)
Solutions
- Verify the path exists (and is absolute) before calling register_file
- Check the upstream producer of the file actually wrote it (earlier step may have failed silently)
- Use Path(...).resolve() to normalize relative paths against an explicit base
Example fix
# before
rec = manager.register_file(p)
# after
p = Path(p).resolve()
if not p.is_file():
raise FileNotFoundError(f"expected export at {p}")
rec = manager.register_file(p) Defensive patterns
Strategy: type-guard
Validate before calling
p = Path(file_path).resolve()
if not p.is_file():
raise FileNotFoundError(f'missing attachment source: {p}') Type guard
def is_registerable_file(p: str | Path) -> bool:
return Path(p).is_file() Try / catch
try:
rec = manager.register_file(p)
except FileNotFoundError:
p = re_generate_export(); rec = manager.register_file(p) Prevention
- Resolve paths to absolute before registration
- Verify upstream file-producing steps succeeded
- Use manager.get() style None-checks before file ops
When it happens
Trigger: Calling register_file (directly or via load_file/save_upload_file/_persist_single_attachment/report_export_pdf) with a path whose file was moved, deleted, or never written; relative path resolved against an unexpected CWD; typo in the path.
Common situations: Temp file cleaned up before registration; path built from user input that was never validated; running the process from a different working directory so relative paths break; race where an upstream step failed to produce the file.
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
- Workflow logical issues detected for '{config_path}': {forma
- 2
- 1
- YAML root must be a mapping
- Destination already exists: {destination}
AI-assisted analysis of OpenBMB/ChatDev@4fb2db0ea9 (2026-08-27).
Data as JSON: /api/errors/e120bfbe37ea6cf9.
Report an issue: GitHub.