OpenBMB/ChatDev · error · KeyError
Attachment '{attachment_id}' not found
Error message
Attachment '{attachment_id}' not found What it means
AttachmentManager.update_remote_file_id raises KeyError when the attachment_id is not in the in-memory _records registry. It is called after uploading to a provider to store the returned remote file id, so the record must have been registered earlier in the same manager instance.
Source
Thrown at utils/attachments.py:217
size=size,
remote_file_id=remote_file_id,
)
record = AttachmentRecord(ref=ref, kind=kind, description=description, extra=extra or {})
self._records[attachment_id] = record
if persist:
self._persistent_ids.add(attachment_id)
self._save_manifest()
else:
self._persistent_ids.discard(attachment_id)
if ref.sha256:
self._hash_index[ref.sha256] = attachment_id
return record
def update_remote_file_id(self, attachment_id: str, remote_file_id: str) -> None:
"""Attach a provider file_id to an existing record (after upload)."""
record = self._records.get(attachment_id)
if not record:
raise KeyError(f"Attachment '{attachment_id}' not found")
record.ref.remote_file_id = remote_file_id
if attachment_id in self._persistent_ids:
self._save_manifest()
def get(self, attachment_id: str) -> AttachmentRecord | None:
return self._records.get(attachment_id)
def to_message_block(self, attachment_id: str) -> MessageBlock:
record = self._records.get(attachment_id)
if not record:
raise KeyError(f"Attachment '{attachment_id}' not found")
return record.as_message_block()
def list_records(self) -> Dict[str, AttachmentRecord]:
return dict(self._records)
def export_manifest(self) -> Dict[str, Any]:
return {View on GitHub (pinned to 4fb2db0ea9)
Solutions
- Confirm the registration call (register_file/register_bytes) succeeded and use the id it returned
- Use the same AttachmentManager instance for register and update
- Catch KeyError and re-register/re-upload the attachment to get a fresh id
Example fix
# before
manager.update_remote_file_id(att_id, remote_id)
# after
if manager.get(att_id) is None:
raise UnknownAttachment(att_id)
manager.update_remote_file_id(att_id, remote_id) Defensive patterns
Strategy: validation
Validate before calling
if manager.get(attachment_id) is None:
raise UnknownAttachment(attachment_id) Type guard
def has_attachment(m, aid: str) -> bool:
return m.get(aid) is not None Try / catch
try:
manager.update_remote_file_id(aid, rid)
except KeyError:
rec = re_register_source(); manager.update_remote_file_id(rec.attachment_id, rid) Prevention
- Use get() (None-returning) for lookups
- Keep register+update on the same manager instance/process
- Reload persisted manifest before cross-process updates
When it happens
Trigger: Calling update_remote_file_id after a server restart (records are in-memory), with a typo'd id, or before register_file/register_bytes created the record.
Common situations: State lost across process restarts or between manager instances; multi-worker deployment where registration and update hit different workers; race where the record is evicted before the upload completes.
Related errors
- memory store {attachment.name} not found
- Failed to persist attachment '{attachment.name or attachment
- Workspace or node context missing for attachment persistence
- Attachment missing data for persistence
- Attachment source not found: {source}
AI-assisted analysis of OpenBMB/ChatDev@4fb2db0ea9 (2026-08-27).
Data as JSON: /api/errors/8f3fbfc6b0c6421d.
Report an issue: GitHub.