From cae367db2879e7c9e1e403fb075d9a43788a3336 Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Wed, 19 Nov 2025 16:25:58 -0700 Subject: [PATCH] fix: migrate geo shapes with props.text during Automerge load MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Geo shapes saved before the tldraw schema change have props.text which is no longer valid. This causes ValidationError on page reload when shapes are loaded from Automerge: "ValidationError: At shape(type = geo).props.text: Unexpected property" The migration logic was only in JSON import (CustomMainMenu.tsx), but shapes loading from Automerge also need migration. This fix adds the props.text → props.richText migration to the sanitizeRecord function in AutomergeToTLStore.ts, ensuring geo shapes are properly migrated when loaded from Automerge, matching the behavior during JSON import. The original text is preserved in meta.text for backward compatibility with search and other features that reference it. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/automerge/AutomergeToTLStore.ts | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/automerge/AutomergeToTLStore.ts b/src/automerge/AutomergeToTLStore.ts index dee47a5..f357e85 100644 --- a/src/automerge/AutomergeToTLStore.ts +++ b/src/automerge/AutomergeToTLStore.ts @@ -769,6 +769,33 @@ export function sanitizeRecord(record: any): TLRecord { } } + // CRITICAL: Convert props.text to props.richText for geo shapes (tldraw schema change) + // tldraw no longer accepts props.text on geo shapes - must use richText + // This migration handles shapes that were saved before the schema change + if (sanitized.type === 'geo' && 'text' in sanitized.props && typeof sanitized.props.text === 'string') { + const textContent = sanitized.props.text + + // Convert text string to richText format for tldraw + sanitized.props.richText = { + type: 'doc', + content: textContent ? [{ + type: 'paragraph', + content: [{ + type: 'text', + text: textContent + }] + }] : [] + } + + // CRITICAL: Preserve original text in meta.text for backward compatibility + // This is used by search (src/utils/searchUtils.ts) and other legacy code + if (!sanitized.meta) sanitized.meta = {} + sanitized.meta.text = textContent + + // Remove invalid props.text + delete sanitized.props.text + } + // CRITICAL: Fix richText structure for geo shapes (preserve content) if (sanitized.type === 'geo' && sanitized.props.richText) { if (Array.isArray(sanitized.props.richText)) {