Skip to content

[Bug]: Matchmaker crashes with uncaught SyntaxError when localStorage bookmark data is corrupted #566

Description

@nyxsky404

Bug Description

In src/pages/Matchmaker.jsx (lines 88-91), bookmarks are loaded from localStorage inside a useState lazy initializer:

const [bookmarks, setBookmarks] = useState(() => {
  const cached = localStorage.getItem(`matchmaker_bookmarks_${user?.uid || "guest"}`);
  return cached ? JSON.parse(cached) : [];
});

If the stored value is malformed — from a write that was interrupted mid-way by a storage quota error, a browser extension overwriting the key, or any previous version of the code writing non-JSON — JSON.parse throws a SyntaxError synchronously inside the lazy initializer. This happens during component construction, before any error boundary can intercept it, and the entire Matchmaker page goes blank with an unhandled exception.

There is also a secondary problem: when user is undefined during initial auth loading, the key defaults to matchmaker_bookmarks_guest. Once auth resolves and the user logs in, the key changes to matchmaker_bookmarks_${uid} — any bookmarks saved as a guest are silently abandoned with no migration.

How to reproduce

  1. Open DevTools > Application > Local Storage
  2. Set matchmaker_bookmarks_guest to not valid json
  3. Navigate to /dashboard/matchmaker
  4. Page crashes

Proposed fix

Wrap the parse in a try/catch and purge the corrupt entry. Also handle the guest-to-user migration on login:

const safeLoadBookmarks = (key) => {
  try {
    const raw = localStorage.getItem(key);
    if (!raw) return [];
    const parsed = JSON.parse(raw);
    return Array.isArray(parsed) ? parsed : [];
  } catch {
    localStorage.removeItem(key);
    return [];
  }
};

const [bookmarks, setBookmarks] = useState(() => {
  const userKey = `matchmaker_bookmarks_${user?.uid || "guest"}`;
  if (user?.uid) {
    const saved = safeLoadBookmarks(userKey);
    if (saved.length === 0) {
      const guestSaved = safeLoadBookmarks("matchmaker_bookmarks_guest");
      if (guestSaved.length > 0) {
        localStorage.setItem(userKey, JSON.stringify(guestSaved));
        localStorage.removeItem("matchmaker_bookmarks_guest");
        return guestSaved;
      }
    }
    return saved;
  }
  return safeLoadBookmarks(userKey);
});

Metadata

Metadata

Assignees

Labels

NSoC'26NSoC 2026backendBackend/Firebase related changesbugSomething isn't workingfrontendFrontend related changes (HTML/CSS/JS/React)gssocGirlScript Summer of Codegssoc26GirlScript Summer of Code 2026needs-reviewIssue needs reviewnsocNSoC

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions