{"record":{"id":"6de0247eb57a9a0e","repo":"koala73/worldmonitor","slug":"invalid-telegram-username","errorCode":null,"errorMessage":"Invalid Telegram username","messagePattern":"Invalid Telegram username","errorType":"validation","errorClass":"TelegramLookupError","httpStatus":400,"severity":"warning","filePath":"src/services/telegram-intel.ts","lineNumber":273,"sourceCode":"  } catch (error) {\n    // A truncated or non-JSON 200 is the same class of upstream blip as a 5xx;\n    // handling it differently would strand the panel on exactly the shape the\n    // relay's own normalization fallthrough exists to tolerate.\n    const stale = staleFallback();\n    if (stale) return stale;\n    throw error;\n  }\n  cachedResponse = json;\n  cachedAt = Date.now();\n  return json;\n}\n\nexport async function fetchTelegramChannelPreview(username: string): Promise<TelegramChannelPreview> {\n  // Normalize here rather than trusting callers: an un-normalized value became\n  // both the cache key and the wire value, so `@foo` and `t.me/foo` would hold\n  // separate entries and issue requests the edge then rejects.\n  const cacheKey = normalizeTelegramUsername(username);\n  if (!cacheKey) throw new TelegramLookupError('Invalid Telegram username', 400);\n  const cached = previewCache.get(cacheKey);\n  if (cached && cached.expiresAt > Date.now()) return cached.data;\n\n  const inflight = previewInflight.get(cacheKey);\n  if (inflight) return inflight;\n\n  const request = (async () => {\n    const preview = parseTelegramChannelPreview(await readJson(await fetch(telegramResolveUrl(cacheKey), {\n      signal: createTimeoutSignal(PREVIEW_REQUEST_TIMEOUT_MS),\n    })));\n    setLookupCache(previewCache, cacheKey, preview, RESOLVE_CACHE_TTL);\n    return preview;\n  })();\n\n  previewInflight.set(cacheKey, request);\n  try {\n    return await request;\n  } finally {","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/koala73/worldmonitor/blob/9361220cc013571781071f0206e4d80fd14b2f7f/src/services/telegram-intel.ts#L255-L291","documentation":"fetchTelegramChannelPreview normalizes the given username and uses the result as both cache key and wire value; if normalization yields an empty string (no valid handle extractable), it throws TelegramLookupError('Invalid Telegram username', 400) before any network call. This intentionally replaces older behavior where un-normalized inputs caused duplicate cache entries and rejected requests.","triggerScenarios":"Calling fetchTelegramChannelPreview('') with an empty string, whitespace, a bare '@', a full URL like 'https://t.me/' with no path, or any string normalizeTelegramUsername cannot reduce to a valid handle.","commonSituations":"Users typing full t.me URLs or handles with @/spaces into a watchlist form; empty form submission; pasted invite links (t.me/+hash) that don't map to a public username; copy-paste with invisible characters.","solutions":["Run the input through normalizeTelegramUsername first and refuse empty results before calling the API.","Trim and strip leading '@' / 'https://t.me/' prefixes from user input before invoking.","Show inline form validation ('enter a public channel handle') instead of surfacing the thrown error.","Exclude private invite links (+hash) since they have no public username."],"exampleFix":"// before\nawait fetchTelegramChannelPreview(userInput); // throws 400 for 'https://t.me/'\n// after\nconst handle = normalizeTelegramUsername(userInput);\nif (!handle) { showFormError('Enter a valid public channel handle'); return; }\nawait fetchTelegramChannelPreview(handle);","handlingStrategy":"validation","validationCode":"import { normalizeTelegramUsername } from '../services/telegram-intel';\nconst handle = normalizeTelegramUsername(rawInput);\nif (!handle) {\n  showFormError('Enter a valid public channel handle');\n  return;\n}\n","typeGuard":"function isValidTelegramHandle(input: string): boolean {\n  return normalizeTelegramUsername(input).length > 0;\n}\n","tryCatchPattern":"try {\n  const preview = await fetchTelegramChannelPreview(handle);\n} catch (e) {\n  if (e instanceof TelegramLookupError && e.status === 400) {\n    showFormError('Invalid Telegram username');\n  } else throw e;\n}\n","preventionTips":["Validate handles in the form layer before invoking the fetch service","Normalize once at input boundaries; never pass raw URLs or '@'-prefixed strings","Exclude private invite links (t.me/+hash) from preview lookups","Trim whitespace and strip invisible characters from pasted input"],"tags":["validation","telegram","username","invalid-input"],"backgroundTag":"invalid-username-format","analyzedSha":"9361220cc013571781071f0206e4d80fd14b2f7f","analyzedAt":"2026-09-01T10:32:37.851Z","contentChangedAt":"2026-09-01T10:32:37.851Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}