{"record":{"id":"715a4dad36c735a0","repo":"koala73/worldmonitor","slug":"failed-to-extract-push-subscription-keys","errorCode":null,"errorMessage":"Failed to extract push subscription keys.","messagePattern":"Failed to extract push subscription keys\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/services/push-notifications.ts","lineNumber":167,"sourceCode":"  let sub = await reg.pushManager.getSubscription();\n  if (!sub) {\n    sub = await reg.pushManager.subscribe({\n      userVisibleOnly: true,\n      applicationServerKey: urlBase64ToUint8Array(VAPID_PUBLIC_KEY) as BufferSource,\n    });\n  }\n\n  const payload = subscriptionToPayload(sub);\n  if (!payload) {\n    // Chrome occasionally hands back a subscription with null keys on\n    // first-grant. Unsubscribe and retry once.\n    await sub.unsubscribe().catch(() => {});\n    const retry = await reg.pushManager.subscribe({\n      userVisibleOnly: true,\n      applicationServerKey: urlBase64ToUint8Array(VAPID_PUBLIC_KEY) as BufferSource,\n    });\n    const retryPayload = subscriptionToPayload(retry);\n    if (!retryPayload) throw new Error('Failed to extract push subscription keys.');\n    await postSubscription(retryPayload, expectedUserId);\n    return retryPayload;\n  }\n\n  await postSubscription(payload, expectedUserId);\n  return payload;\n}\n\n/**\n * Shape the error thrown when `/api/notification-channels` rejects a\n * subscription.\n *\n * Every rejection on that route answers with a distinct `error` code —\n * `endpoint host is not a recognised push service`, `pro_required`,\n * `Invalid JSON body`, `MISSING_USER_ID`, … — but the throw used to carry only\n * the HTTP status. That made WORLDMONITOR-XR (3 events / 2 users, Chrome on\n * macOS) permanently undiagnosable: a bare \"(400)\" cannot distinguish an\n * unrecognised push host from a malformed body from an entitlement denial, and","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/koala73/worldmonitor/blob/eeab0a219fce0f02a00603b532dbae9041b934ac/src/services/push-notifications.ts#L149-L185","documentation":"UI error in subscribeToPush: the push subscription's payload could not be built because encryption keys were null. This is the known Chrome first-grant bug — the code unsubscribes and retries once; the error means the retry also produced null keys.","triggerScenarios":"Thrown at src/services/push-notifications.ts:167 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Retry subscribing — the Chrome null-keys bug is intermittent","Reload the page and try again if the immediate retry already failed","Report browser/version if it consistently fails — some environments (e.g. certain privacy modes) never hand back keys"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"eeab0a219fce0f02a00603b532dbae9041b934ac","analyzedAt":"2026-08-21T16:51:25.751Z","contentChangedAt":"2026-08-21T16:51:25.751Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}