fix: create metadata.json when joining conversation if it doesn't exist
Problem
Socket connection fails when metadata.json doesn't exist in .openhands-state/sessions/[conversation_id]/ directory. This causes FileNotFoundError in _update_conversation_for_event when calling conversation_store.get_metadata(conversation_id).
Root Cause
There are two ways to create/join conversations in OpenHands:
-
POST /api/conversation → WebSocket (✅ Works correctly)
- POST API creates metadata.json during session initialization
- WebSocket connection with returned conversation_id works fine
-
Direct WebSocket with custom conversation_id (❌ Fails)
- WebSocket connection with user-specified conversation_id
- No metadata.json is created, causing FileNotFoundError
Solution
- Modified
join_conversationmethod to check if metadata.json exists - If not found, create a new metadata.json file with default conversation settings
- Preserves existing metadata for reconnections to existing sessions
- Ensures both session creation methods work consistently
Testing
- [x] POST API → WebSocket (existing functionality, still works)
- [x] Direct WebSocket with new conversation_id (now works)
- [x] Direct WebSocket with existing conversation_id (reconnection works)
- [x] Multiple clients joining the same session
Related Issues
Fixes #6804 (similar metadata.json not found errors)
This change ensures that regardless of how a conversation is initiated, the metadata.json file will always exist when needed.
I guess you have some sort of custom use case here where you are not calling the POST /api/conversations endpoint to create a conversation before calling the websocket? OpenHands used to work this way when the conversation and the websocket connection were more closely bound. We did eventually go in a different direction separating the conversation from the websocket lifecycle, and have recently gone further in this direction with the introduction of explicit /start and /stop endpoints for conversations.
Is running everything over a single connection something you require?
I guess you have some sort of custom use case here where you are not calling the
POST /api/conversationsendpoint to create a conversation before calling the websocket? OpenHands used to work this way when the conversation and the websocket connection were more closely bound.
A clarification here: conversations will not have metadata.json also if they're created from CLI or other entry points in OH, which are not via agent_session.py. Then they could be requested or reloaded via agent_session.py.
Thanks for the review.
fix: move metadata creation check to ConversationValidator as suggested by @tofarr implementing metadata.json creation check in ConversationValidator._ensure_metadata_exists() instead of conversation_manager.