koala73/worldmonitor · error

Telegram watchlist could not be saved

Error message

Telegram watchlist could not be saved

What it means

setTelegramWatchlistEntries serializes the normalized entry list and writes it to localStorage under STORAGE_KEY; any storage failure (quota exceeded, private-browsing restrictions, storage disabled or evicted) is caught and rethrown as 'Telegram watchlist could not be saved'. Persistence failed, so the in-memory dispatch is skipped and the caller knows the list was not saved.

Source

Thrown at src/services/telegram-watchlist.ts:89

export function getTelegramWatchlistEntries(): TelegramWatchlistEntry[] {
  try {
    const parsed = safeParseJson<unknown>(localStorage.getItem(STORAGE_KEY));
    if (!Array.isArray(parsed)) return [];

    return normalizeEntries(parsed);
  } catch {
    return [];
  }
}

export function setTelegramWatchlistEntries(entries: TelegramWatchlistEntry[]): TelegramWatchlistEntry[] {
  const next = normalizeEntries(entries || []);

  try {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(next));
  } catch {
    throw new Error('Telegram watchlist could not be saved');
  }

  dispatch(next);
  return next;
}

export function addTelegramWatchlistEntry(entry: TelegramWatchlistEntry): TelegramWatchlistEntry[] {
  const normalized = coerceEntry(entry);
  if (!normalized) return getTelegramWatchlistEntries();

  const current = getTelegramWatchlistEntries();
  const existing = current.findIndex(item => item.username === normalized.username);
  if (existing >= 0) {
    const existingEntry = current[existing];
    if (!existingEntry) return current;
    current[existing] = normalized.title
      ? { username: existingEntry.username, title: normalized.title }
      : existingEntry;

View on GitHub (pinned to 9361220cc0)

Solutions

  1. Wrap watchlist writes in try/catch and keep an in-memory list so the UI still works for the session when persistence fails.
  2. Check storage availability up front (probe localStorage with a test write) and switch to a memory-only mode with a 'not persisted' notice.
  3. Free quota by pruning other localStorage keys or trimming watchlist entries (e.g. drop unused preview caches) before retrying.
  4. Offer an export/import (JSON download) fallback so users on restricted browsers don't lose their watchlist.

Example fix

// before
addTelegramWatchlistEntry(entry); // throws when storage is blocked
// after
try {
  addTelegramWatchlistEntry(entry);
} catch {
  memoryWatchlist.push(entry);
  showToast('Watchlist saved for this session only (storage unavailable)');
}
Defensive patterns

Strategy: try-catch

Validate before calling

function storageAvailable(): boolean {
  try {
    const k = '__wm_probe__';
    localStorage.setItem(k, '1');
    localStorage.removeItem(k);
    return true;
  } catch {
    return false;
  }
}

Try / catch

try {
  setTelegramWatchlistEntries(next);
} catch {
  memoryWatchlist = next; // session-only fallback
  showToast('Storage unavailable — watchlist kept for this session only');
}

Prevention

When it happens

Trigger: Calling setTelegramWatchlistEntries (directly or via addTelegramWatchlistEntry/removeTelegramWatchlistEntry) when localStorage.setItem throws: quota exceeded (QuotaExceededError), Safari private mode, storage disabled by browser policy, or a page origin with storage partitioned away.

Common situations: Users in private/incognito browsing with storage blocked; localStorage full from other app data; embedded webviews or strict privacy settings disabling storage; corporate browsers with site-data restrictions.

Related errors


AI-assisted analysis of koala73/worldmonitor@9361220cc0 (2026-09-01). Data as JSON: /api/errors/050d396f7f8e7e54. Report an issue: GitHub.