{"record":{"id":"63003deb8a91c813","repo":"tw93/Pake","slug":"badge-count-must-be-a-finite-number","errorCode":null,"errorMessage":"Badge count must be a finite number.","messagePattern":"Badge count must be a finite number\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src-tauri/src/inject/event.js","lineNumber":1315,"sourceCode":"// pages running inside the webview can drive the macOS dock badge (and\n// taskbar badge on Linux/Windows). Installs synchronously instead of waiting\n// for DOMContentLoaded so feature-detection on Notification/setAppBadge\n// returns the polyfill before site scripts run.\n(function () {\n  const invoke = window.__TAURI__?.core?.invoke;\n  if (!invoke) return;\n\n  let permVal = \"granted\";\n  let lastNotifTime = 0;\n  let lastNotif = null;\n  // Pages that drive the badge directly via setAppBadge own its lifecycle;\n  // notifications-driven counts auto-clear on the next user interaction.\n  let pageManagedBadge = false;\n  let autoBadgeActive = false;\n\n  const normalizeBadgeCount = (count) => {\n    if (typeof count !== \"number\" || !Number.isFinite(count)) {\n      throw new TypeError(\"Badge count must be a finite number.\");\n    }\n    const normalized = Math.floor(count);\n    return normalized > 0 ? Math.min(normalized, 99999) : null;\n  };\n  const setBadge = (count) => {\n    pageManagedBadge = true;\n    autoBadgeActive = false;\n    return invoke(\"set_dock_badge\", { count }).catch(() => {});\n  };\n  const clearBadge = () => invoke(\"clear_dock_badge\").catch(() => {});\n  const setLabel = (label) => {\n    pageManagedBadge = true;\n    autoBadgeActive = false;\n    return invoke(\"set_dock_badge_label\", { label }).catch(() => {});\n  };\n  const incrementAutoBadge = () => {\n    if (pageManagedBadge) return Promise.resolve();\n    autoBadgeActive = true;","sourceCodeStart":1297,"sourceCodeEnd":1333,"githubUrl":"https://github.com/tw93/Pake/blob/c8fe8a3f1a115428e3555c06b3de9b7458aa0d54/src-tauri/src/inject/event.js#L1297-L1333","documentation":"Pake's badge normalization (in the injected event.js) rejects any badge count that is not a finite JavaScript number. The injected script exposes a setBadge API to the web page; before forwarding it to the native window it validates the value, throwing a TypeError for NaN, Infinity, -Infinity, or non-number types. This guards the native IPC boundary from garbage values.","triggerScenarios":"A page (or injected code) calls pake's setBadge with a non-number value (string, undefined, null) or a non-finite number (NaN, Infinity).","commonSituations":"Page scripts computing a count from a fetch result that returned undefined; a notification counter initialized before data loads (NaN); passing a numeric string like '3' from an input element.","solutions":["Ensure the caller passes a real number: Number(...) the value before calling setBadge.","Check Number.isFinite(count) at the call site before invoking setBadge.","If the intent is to clear the badge, omit the call or use the API's clear path instead of passing NaN/null."],"exampleFix":"// before\nsetBadge(unreadCountFromResponse);\n// after\nconst count = Number(unreadCountFromResponse);\nif (Number.isFinite(count)) setBadge(count);","handlingStrategy":"type-guard","validationCode":"function isValidBadgeCount(v) { return typeof v === 'number' && Number.isFinite(v); }\nif (!isValidBadgeCount(raw)) throw new TypeError('Badge count must be a finite number.');","typeGuard":"const isValidBadgeCount = (v) => typeof v === 'number' && Number.isFinite(v);","tryCatchPattern":"try { setBadge(raw); } catch (e) { if (e instanceof TypeError) { console.warn('badge skipped:', raw); } else { throw e; } }","preventionTips":["Coerce with Number() and check Number.isFinite before any badge update","Guard async-derived counts against undefined after failed fetches","Centralize badge updates in one helper that validates input"],"tags":["badge","type-error","injected-javascript"],"backgroundTag":"invalid-argument-value","analyzedSha":"c8fe8a3f1a115428e3555c06b3de9b7458aa0d54","analyzedAt":"2026-09-20T12:02:36.283Z","contentChangedAt":"2026-09-20T12:02:36.283Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}