OpenBMB/ChatDev · error · RuntimeError
Workspace or node context missing for attachment persistence
Error message
Workspace or node context missing for attachment persistence
What it means
An attachment needs to be written to disk but the executor cannot resolve a destination: context.global_state lacks 'python_workspace_root' or the node_id is empty. Persistence is aborted rather than writing to an unknown location.
Source
Thrown at runtime/node/executor/agent_executor.py:1103
def _persist_single_attachment(self, store: Any, block: MessageBlock, node_id: str) -> None:
attachment = block.attachment
if attachment is None:
return
if attachment.remote_file_id and not attachment.data_uri and not attachment.local_path:
record = store.register_remote_file(
remote_file_id=attachment.remote_file_id,
name=attachment.name or attachment.attachment_id or "remote_file",
mime_type=attachment.mime_type,
size=attachment.size,
kind=block.type,
attachment_id=attachment.attachment_id,
)
block.attachment = record.ref
return
workspace_root = self.context.global_state.get("python_workspace_root")
if workspace_root is None or not node_id:
raise RuntimeError("Workspace or node context missing for attachment persistence")
target_dir = workspace_root / "generated" / node_id
target_dir.mkdir(parents=True, exist_ok=True)
inferred_mime = attachment.mime_type or self._guess_mime_from_data_uri(attachment.data_uri)
attachment.mime_type = inferred_mime
data_bytes = self._decode_data_uri(attachment.data_uri) if attachment.data_uri else None
target_path = None
if data_bytes is None and attachment.local_path:
target_path = target_dir / (attachment.name or self._make_generated_filename(attachment))
import shutil
shutil.copy2(attachment.local_path, target_path)
elif data_bytes is not None:
target_path = target_dir / (attachment.name or self._make_generated_filename(attachment))
with open(target_path, "wb") as handle:
handle.write(data_bytes)View on GitHub (pinned to 4fb2db0ea9)
Solutions
- Ensure the workflow bootstrap sets context.global_state['python_workspace_root'] to a Path
- Run the node through the normal workflow engine so workspace provisioning happens
- If embedding the executor manually, populate global_state and use non-empty node ids
Example fix
# before
context.global_state = {}
# after
context.global_state['python_workspace_root'] = Path('/srv/workspaces/run-1') Defensive patterns
Strategy: validation
Validate before calling
root = context.global_state.get('python_workspace_root')
assert root is not None and node_id, 'workspace context missing' Prevention
- Bootstrap workspace state via the standard workflow engine
- Assert required global_state keys in executor setup
When it happens
Trigger: Executing an agent node with attachments when the workspace root was never initialized in global state, or node_id is falsy (e.g. empty string id).
Common situations: Running the executor outside the standard workflow bootstrap (unit tests, embedded usage); workspace provisioning step skipped or failed earlier; misconfigured runtime context.
Related errors
- memory store {attachment.name} not found
- Failed to persist attachment '{attachment.name or attachment
- Attachment missing data for persistence
- Attachment source not found: {source}
- register_bytes expects bytes or bytearray data
AI-assisted analysis of OpenBMB/ChatDev@4fb2db0ea9 (2026-08-27).
Data as JSON: /api/errors/b2d758349bdd6337.
Report an issue: GitHub.