{
  "id": 2388956,
  "title": "The Bug That Only Showed Up in a Second Tab: Debugging a Multi-Tab localStorage Race Condition",
  "url": "https://urgent.news/2026/08/21/the-bug-that-only-showed-up-in-a-second-tab-debugging-a-multi-tab",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-08-21T14:16:13.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/mehwish_e1e7e09af6e0754ed/the-bug-that-only-showed-up-in-a-second-tab-debugging-a-multi-tab-localstorage-race-condition-4kjk"
  },
  "original_language": "en",
  "account": "This story details a debugging process undertaken for a multi-tab localStorage race condition in the InnerHue app. InnerHue is a mood-tracking application that stores entries in localStorage through a Zustand store. The bug in question was that entries would occasionally vanish or get overwritten when the app was opened in multiple tabs.\n\nAfter investigation, it was discovered that the Zustand store, responsible for maintaining an in-memory copy of moodHistory, didn't monitor changes originating from other tabs. Hence, each tab maintained its own outdated snapshot of the data. The first tab to write to the localStorage would overwrite the data from the second tab, resulting in the aforementioned race condition.\n\nTo rectify this issue, a listener was added to the window's storage event. This listener invoked useMoodStore.persist.rehydrate() whenever the mood-storage key was altered in another tab. This ensured that all open tabs remained synchronized, overcoming the race condition.\n\nInterestingly, while investigating the race condition, another bug was uncovered. This one involved duplicate entries being generated each time the mood page was accessed. Further analysis revealed that this was due to the addMood() function being invoked directly within a useEffect without any safeguards. In development mode, React Strict Mode's double invocation of effects caused the function to be executed twice.\n\nTo address this issue, a useRef guard was implemented. This ensured that the function would only be triggered once per genuine page visit. Both bugs originated from the same localStorage write path, hence they were resolved collectively in a single pull request.\n\nThe incident serves as a reminder of how bugs that only surface under specific conditions, like multiple tabs open, can be easily overlooked during typical development testing. It also emphasizes the importance of rigorously testing state management code, especially for scenarios involving concurrent access, not just single-tab flows.",
  "summary": "This is a submission for DEV's Summer Bug Smash: Smash Stories powered by Sentry . I was working on InnerHue, a mood-tracking app that stores mood entries in localStorage via a Zustand store. The reported bug: open the app in two tabs, log a mood in each, and entries would randomly go missing or get overwritten. The investigation The Zustand store ( lib/useMoodStore.ts ) kept an in-memory copy of…",
  "key_points": [],
  "editors_take": null,
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}