{"record":{"id":"2263b48307b003bf","repo":"OpenBMB/ChatDev","slug":"attachment-missing-data-for-persistence","errorCode":null,"errorMessage":"Attachment missing data for persistence","messagePattern":"Attachment missing data for persistence","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"runtime/node/executor/agent_executor.py","lineNumber":1123,"sourceCode":"        target_dir = workspace_root / \"generated\" / node_id\n        target_dir.mkdir(parents=True, exist_ok=True)\n\n        inferred_mime = attachment.mime_type or self._guess_mime_from_data_uri(attachment.data_uri)\n        attachment.mime_type = inferred_mime\n\n        data_bytes = self._decode_data_uri(attachment.data_uri) if attachment.data_uri else None\n        target_path = None\n\n        if data_bytes is None and attachment.local_path:\n            target_path = target_dir / (attachment.name or self._make_generated_filename(attachment))\n            import shutil\n            shutil.copy2(attachment.local_path, target_path)\n        elif data_bytes is not None:\n            target_path = target_dir / (attachment.name or self._make_generated_filename(attachment))\n            with open(target_path, \"wb\") as handle:\n                handle.write(data_bytes)\n        else:\n            raise ValueError(\"Attachment missing data for persistence\")\n\n        record = store.register_file(\n            target_path,\n            kind=block.type,\n            display_name=attachment.name or target_path.name,\n            mime_type=attachment.mime_type,\n            attachment_id=attachment.attachment_id,\n            copy_file=False,\n            persist=True,\n        )\n        block.attachment = record.ref\n\n    def _decode_data_uri(self, data_uri: Optional[str]) -> Optional[bytes]:\n        if not data_uri:\n            return None\n        if not data_uri.startswith(\"data:\"):\n            return None\n        header, _, payload = data_uri.partition(\",\")","sourceCodeStart":1105,"sourceCodeEnd":1141,"githubUrl":"https://github.com/OpenBMB/ChatDev/blob/4fb2db0ea90375ce1059f44fe03ffbd191a7a169/runtime/node/executor/agent_executor.py#L1105-L1141","documentation":"The attachment has neither a remote_file_id, nor a local_path, nor data_bytes to write — nothing can be persisted. Raised by _persist_single_attachment when every data source is absent.","triggerScenarios":"Message block references an attachment whose ref was never populated (no data_uri, no local_path, no bytes, no remote id).","commonSituations":"LLM emitting an attachment block with only metadata; upstream node dropped attachment payloads when cloning messages; deserialization losing binary fields.","solutions":["Verify the producing node actually attached data (data_uri, local_path, or bytes)","Check message cloning/serialization paths don't strip attachment payloads","If the attachment is intentionally empty, skip persistence for blocks without data"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"a = block.attachment\nhas_data = a and (a.remote_file_id or a.local_path or a.data_uri or getattr(a, 'data_bytes', None))\nif not has_data:\n    continue  # skip empty attachment blocks","typeGuard":"def has_persistable_data(a) -> bool:\n    return bool(a and (a.remote_file_id or a.local_path or a.data_uri))","tryCatchPattern":null,"preventionTips":["Validate attachment blocks when constructing messages","Test clone/serialize round-trips of attachment payloads"],"tags":["attachments","validation","empty-payload"],"backgroundTag":"empty-attachment-payload","analyzedSha":"4fb2db0ea90375ce1059f44fe03ffbd191a7a169","analyzedAt":"2026-08-27T14:35:29.622Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}