From ca9f250de89c4965736285152103630e26b94bb4 Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Sun, 16 Nov 2025 21:15:56 -0700 Subject: [PATCH] fix: handle concurrent Automerge document access with try-catch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When multiple clients try to load the same room simultaneously, repo.find() throws "Document unavailable" error if the document isn't in the repo yet. Wrapped repo.find() in try-catch to create a new handle when document isn't available, allowing multiple boards to load the same page concurrently. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/automerge/useAutomergeSyncRepo.ts | 34 +++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/src/automerge/useAutomergeSyncRepo.ts b/src/automerge/useAutomergeSyncRepo.ts index fbd99d0..da44d2f 100644 --- a/src/automerge/useAutomergeSyncRepo.ts +++ b/src/automerge/useAutomergeSyncRepo.ts @@ -146,11 +146,37 @@ export function useAutomergeSync(config: AutomergeSyncConfig): TLStoreWithStatus let handle: DocHandle if (documentId) { - // Convert document ID to Automerge URL format and find it - console.log(`🔍 Finding document ${documentId} via network sync`) + // FIXED: Use repo.find() but wrap in try-catch for concurrent access + // repo.find() throws immediately if document isn't available in the repo + // Multiple clients can safely call find() on the same document ID + console.log(`🔍 Finding or creating document ${documentId} via network sync`) const docUrl = `automerge:${documentId}` as const - handle = await repo.find(docUrl as any) - console.log(`✅ Got handle for document: ${handle.documentId}, isReady: ${handle.isReady()}`) + + try { + // Try to find the existing document - this is synchronous + // It will throw if the document isn't in the repo yet + handle = repo.find(docUrl as any) + console.log(`✅ Found existing document handle: ${handle.documentId}, isReady: ${handle.isReady()}`) + } catch (error) { + // If find() throws (document unavailable), the document doesn't exist in this repo yet + // This is normal for concurrent access - just create a new handle + // The network sync will merge changes from other clients + console.warn(`⚠️ Document ${documentId} not in repo yet, creating new handle:`, error) + handle = repo.create() + console.log(`📝 Created new document handle with ID: ${handle.documentId}`) + + // Update the server with this new document ID for future clients + try { + await fetch(`${workerUrl}/room/${roomId}/documentId`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ documentId: handle.documentId }) + }) + console.log(`✅ Updated document ID on server: ${handle.documentId}`) + } catch (updateError) { + console.error(`❌ Failed to update document ID on server:`, updateError) + } + } } else { // Create a new document and register its ID with the server handle = repo.create()