Skip to content

Bits of .NET

Daily micro-tips for C#, SQL, performance, and scalable backend engineering.

  • Asp.Net Core
  • C#
  • SQL
  • JavaScript
  • CSS
  • About
  • ErcanOPAK.com
  • No Access
  • Privacy Policy
JavaScript

JavaScript: Why localStorage Silently Throws in Private Browsing Mode

- 31.08.26 | 31.08.26 - ErcanOPAK

⚡ localStorage Isn’t Always There — Code Like It Might Not Be

Code that calls localStorage.setItem() directly works perfectly in normal testing, then throws an uncaught exception and breaks the whole page for users in Safari’s Private Browsing mode, some locked-down corporate browsers, or with storage explicitly disabled.

🐞 The Problem

function saveDraft(text) {
  localStorage.setItem('draft', text); // throws in some environments
}
// Safari Private Browsing (older versions), some strict privacy
// settings, or storage quota exceeded: this throws a
// QuotaExceededError or SecurityError - and since it's not
// wrapped, it can break the entire calling function silently.

🔍 Why This Happens

Several real-world situations make localStorage unavailable or
throw on write: Private/Incognito browsing in some browser
versions, storage quota genuinely exceeded, browser settings that
block storage entirely, or the code running inside a sandboxed
iframe with storage access restricted. None of these are edge
cases you can assume away for a public-facing site.

✅ The Fix: Feature-Detect and Wrap in try/catch

  • Check availability once, and always wrap actual reads/writes defensively — availability can change mid-session (e.g. quota fills up).
  • Fall back gracefully: an in-memory variable, a cookie, or simply not persisting the draft is far better than a broken page.

🛡️ Safe Wrapper

function isStorageAvailable() {
  try {
    const testKey = '__storage_test__';
    localStorage.setItem(testKey, testKey);
    localStorage.removeItem(testKey);
    return true;
  } catch {
    return false;
  }
}

function saveDraft(text) {
  try {
    localStorage.setItem('draft', text);
  } catch (err) {
    console.warn('localStorage unavailable, draft not persisted:', err);
    // Fall back to an in-memory variable so the feature still
    // works for this session, just without persistence.
    inMemoryDraft = text;
  }
}

⚠️ Same Applies to sessionStorage and IndexedDB

  • Any browser storage API can be unavailable or throw under similar conditions — the defensive pattern (feature-detect + try/catch + fallback) applies to all of them, not just localStorage.

Storage APIs feel as reliable as a regular variable, but they’re really talking to something outside your code’s control — treating every call as something that CAN fail is what keeps one user’s private browser tab from taking down your whole page.

— JavaScript Tip

Related posts:

JavaScript: Proxy Objects ile Reactive Programming

Handle AJAX Errors Properly: Retry Logic with Exponential Backoff

How to disable ASP.Net button after click to prevent double clicking

Post Views: 3

Post navigation

C#: Why LINQ’s Deferred Execution Silently Re-Runs Your Database Query Every Time You Enumerate It
Windows 11: Fix a Missing TPM 2.0 Error Blocking an Upgrade on a Perfectly Capable PC

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

October 2026
M T W T F S S
 1234
567891011
12131415161718
19202122232425
262728293031  
« Sep    

Most Viewed Posts

  • Get the User Name and Domain Name from an Email Address in SQL (973)
  • How to make theater mode the default for Youtube (952)
  • How to add default value for Entity Framework migrations for DateTime and Bool (939)
  • Get the First and Last Word from a String or Sentence in SQL (847)
  • How to select distinct rows in a datatable in C# (837)
  • How to enable, disable and check if Service Broker is enabled on a database in SQL Server (624)
  • Add Constraint to SQL Table to ensure email contains @ (590)
  • Average of all values in a column that are not zero in SQL (553)
  • How to use Map Mode for Vertical Scroll Mode in Visual Studio (526)
  • Find numbers with more than two decimal places in SQL (468)

Recent Posts

  • CSS: Fix a prefers-color-scheme Media Query That Gets Silently Overridden by a Browser Extension’s Forced Dark Mode
  • Git: Fix a Merge Commit That Silently Drops a File Because Both Branches Deleted It Differently
  • HTML5: Fix a Native Lazy-Loading Image That Never Loads Because It Sits Inside a Hidden Tab Until the User Clicks It
  • The AI Prompt That Traces a Null Reference Exception Back to the Exact Line That First Produced the Null
  • The AI Prompt That Turns a Gym Membership Contract’s Fine Print Into a Plain-English List of Cancellation Steps
  • Photoshop: Fix a Color Profile Mismatch That Makes Printed Output Look Nothing Like What You Saw On Screen
  • WordPress: Fix Search Results That Return Pages From a Theme You Deactivated Months Ago
  • Visual Studio: Fix a Test Project That Builds Fine Alone but Fails to Discover Any Tests After a NuGet Restore
  • ASP.NET Core: Fix a File Upload That Times Out on Slow Connections Only Because Kestrel’s Minimum Data Rate Feature Kicked In
  • JavaScript: Fix an Array Destructuring Default Value That Silently Never Applies Because null Was Passed Instead of Undefined

Most Viewed Posts

  • Get the User Name and Domain Name from an Email Address in SQL (973)
  • How to make theater mode the default for Youtube (952)
  • How to add default value for Entity Framework migrations for DateTime and Bool (939)
  • Get the First and Last Word from a String or Sentence in SQL (847)
  • How to select distinct rows in a datatable in C# (837)

Recent Posts

  • CSS: Fix a prefers-color-scheme Media Query That Gets Silently Overridden by a Browser Extension’s Forced Dark Mode
  • Git: Fix a Merge Commit That Silently Drops a File Because Both Branches Deleted It Differently
  • HTML5: Fix a Native Lazy-Loading Image That Never Loads Because It Sits Inside a Hidden Tab Until the User Clicks It
  • The AI Prompt That Traces a Null Reference Exception Back to the Exact Line That First Produced the Null
  • The AI Prompt That Turns a Gym Membership Contract’s Fine Print Into a Plain-English List of Cancellation Steps

Social

  • ErcanOPAK.com
  • GoodReads
  • LetterBoxD
  • Linkedin
  • The Blog
  • Twitter
© 2026 Bits of .NET | Built with Xblog Plus free WordPress theme by wpthemespace.com