Skip to content

fix(tweet-preview): guard JSON.parse to avoid crashing the modal#996

Open
vimzh wants to merge 3 commits into
supermemoryai:mainfrom
vimzh:fix/tweet-preview-guard-json-parse
Open

fix(tweet-preview): guard JSON.parse to avoid crashing the modal#996
vimzh wants to merge 3 commits into
supermemoryai:mainfrom
vimzh:fix/tweet-preview-guard-json-parse

Conversation

@vimzh
Copy link
Copy Markdown

@vimzh vimzh commented May 24, 2026

TweetPreview runs JSON.parse(data) on the data prop with no try/catch. If a document's stored Twitter metadata is ever malformed (truncated JSON, corrupted serialization, exotic stringified values like "null" or "123"), the parse throws and the React tree rendering the document modal or memory card crashes.

This wraps the parse in a small parseTweetData helper that returns null when:

  • The input is empty or null
  • JSON.parse throws
  • The parsed value isn't a plain object (covers arrays, which would otherwise slip past a typeof === "object" check and crash deeper in enrichTweet)

When parsing returns null the component renders nothing instead of crashing. Also widened the prop type from Tweet to Tweet | string to match what both call sites already pass via as Tweet / as unknown as Tweet.

One thing worth flagging for reviewers: in apps/web/components/document-modal/content/tweet.tsx the TweetPreview branch is entered whenever tweetMetadata is truthy, so malformed metadata now renders an empty container rather than the "Tweet preview unavailable" fallback further down that file. That is strictly better than crashing but not the friendliest UX. Happy to move the validation up into TweetContent in a follow-up if you would prefer the explicit fallback.

vimzh added 2 commits May 24, 2026 11:46
…weet data

TweetPreview was passing the result of `JSON.parse(data)` straight into
`enrichTweet` whenever `data` was a string. If a document's stored tweet
metadata was ever a non-JSON string, truncated JSON, or `"null"` / `"123"`,
the unguarded parse threw and crashed the React tree rendering the
document modal or memory card.

Extract the parse into a `parseTweetData` helper that returns `null` when
the input is missing, fails to parse, or doesn't resolve to an object.
TweetPreview now renders nothing in those cases instead of crashing.

Also widen the prop type from `Tweet` to `Tweet | string` to reflect the
runtime input both call sites already pass.
The previous guard accepted any non-null `typeof === "object"`, which means
`JSON.parse("[]")` or `JSON.parse("[1,2,3]")` slipped through and reached
`enrichTweet` — exactly the class of crash the helper was added to prevent.

Add an `Array.isArray` check so only plain objects are passed downstream.
Copilot AI review requested due to automatic review settings May 24, 2026 07:03
@graphite-app graphite-app Bot requested a review from Dhravya May 24, 2026 07:03
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR makes TweetPreview resilient to tweet data being passed as a JSON string by adding safe parsing and avoiding render-time exceptions on invalid input.

Changes:

  • Added parseTweetData helper to safely parse tweet JSON strings with try/catch.
  • Updated TweetPreview prop type to accept Tweet | string.
  • Short-circuited rendering (return null) when parsing fails.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread apps/web/components/document-cards/tweet-preview.tsx Outdated
Comment thread apps/web/components/document-cards/tweet-preview.tsx Outdated
Comment thread apps/web/components/document-cards/tweet-preview.tsx Outdated
…d data

Copilot review flagged three things:

1. Casting an arbitrary parsed object to Tweet without validating shape
   can still crash inside enrichTweet. Added an isTweetLike type guard
   that requires the 'user' field, which both CustomTweetHeader and the
   downstream enrichTweet expect.
2. Returning null on bad data silently hid the failure. Now render a
   small 'Tweet preview unavailable' fallback (matching the style of
   the existing fallback in document-modal/content/tweet.tsx) and emit
   a console.warn so failures show up during debugging.
3. JSON.parse was running on every render. Wrapped in useMemo keyed by
   the data prop so reparsing only happens when the input changes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants