{"record":{"id":"cc11fba7d38171b0","repo":"GrapesJS/grapesjs","slug":"localstorage-not-available","errorCode":null,"errorMessage":"localStorage not available","messagePattern":"localStorage not available","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/storage_manager/model/LocalStorage.ts","lineNumber":38,"sourceCode":"    if (this.hasLocal(opts, true)) {\n      localStorage.setItem(opts.key!, JSON.stringify(data));\n    }\n    return data;\n  }\n\n  async load(opts: LocalStorageConfig = {}) {\n    let result = {};\n\n    if (this.hasLocal(opts, true)) {\n      result = JSON.parse(localStorage.getItem(opts.key!) || '{}');\n    }\n\n    return result;\n  }\n\n  hasLocal(opts: LocalStorageConfig = {}, thr?: boolean) {\n    if (opts.checkLocal && (!hasWin() || !localStorage)) {\n      if (thr) throw new Error('localStorage not available');\n      return false;\n    }\n\n    return true;\n  }\n}\n","sourceCodeStart":20,"sourceCodeEnd":45,"githubUrl":"https://github.com/GrapesJS/grapesjs/blob/2bdeda85b82b8b9ceae42fd6558cbbcae5ec2d21/packages/core/src/storage_manager/model/LocalStorage.ts#L20-L45","documentation":"The LocalStorage storage manager checks that `window` and `localStorage` exist (when `checkLocal` is enabled). If storage is unavailable — no browser window, storage disabled/blocked, or restricted environments — `hasLocal(opts, true)` throws 'localStorage not available', causing store/load to fail.","triggerScenarios":"Using `storageManager: { type: 'local' }` with `checkLocal: true` in an environment without localStorage: SSR/Node, webviews with storage disabled, iframes with blocked third-party storage, Safari private mode in old versions, or `localStorage` shadowed/undefined.","commonSituations":"Server-side rendering of the editor, loading GrapesJS inside sandboxed iframes, privacy modes or browser settings disabling site data, automated tests in jsdom without localStorage polyfill.","solutions":["Use a different storage type, e.g. `storageManager: { type: 'remote' }` with proper settings, or disable autosave.","Set `checkLocal: false` in LocalStorage options if you know storage exists or want graceful fallback.","Polyfill/stub localStorage in non-browser or test environments (e.g. node-localstorage, jsdom setup).","Implement a custom storage manager for restricted environments."],"exampleFix":"// before\nstorageManager: { type: 'local', options: { checkLocal: true } }\n// after\nstorageManager: { type: 'local', options: { checkLocal: false } }\n// or polyfill in Node/jsdom:\n// global.localStorage = new LocalStorage('./scratch');","handlingStrategy":"fallback","validationCode":"function localStorageAvailable() {\n  try {\n    const k = '__test__';\n    window.localStorage.setItem(k, k);\n    window.localStorage.removeItem(k);\n    return true;\n  } catch { return false; }\n}\nconst storageType = localStorageAvailable() ? 'local' : 'remote';","typeGuard":"function hasLocalStorage(): boolean {\n  try { return typeof window !== 'undefined' && !!window.localStorage; } catch { return false; }\n}","tryCatchPattern":"try {\n  await editor.store();\n} catch (err) {\n  if (err.message === 'localStorage not available') {\n    // switch to remote storage or skip persistence\n    console.warn('Persistence skipped: localStorage unavailable');\n  } else throw err;\n}","preventionTips":["Probe localStorage availability at app startup and choose storageManager.type accordingly","Set checkLocal:false only when you have independently verified storage","Polyfill localStorage in SSR/tests (node-localstorage, jsdom)","Avoid sandboxed iframes with blocked storage for editors that persist locally"],"tags":["storage","localstorage","environment","browser"],"backgroundTag":"localstorage-unavailable","analyzedSha":"2bdeda85b82b8b9ceae42fd6558cbbcae5ec2d21","analyzedAt":"2026-08-30T11:47:52.267Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}