{"record":{"id":"bb66a0a08c58974d","repo":"Freika/dawarich","slug":"mapchannel-failed-to-subscribe-to-family-channel","errorCode":null,"errorMessage":"[MapChannel] Failed to subscribe to family channel:","messagePattern":"\\[MapChannel\\] Failed to subscribe to family channel:","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"app/javascript/maps_maplibre/channels/map_channel.js","lineNumber":65,"sourceCode":"          },\n\n          disconnected() {\n            console.log(\"FamilyLocationsChannel disconnected\")\n            callbacks.disconnected?.(\"family\")\n          },\n\n          received(data) {\n            console.log(\"FamilyLocationsChannel received:\", data)\n            callbacks.received?.({\n              type: \"family_location\",\n              member: data,\n            })\n          },\n        },\n      )\n    }\n  } catch (error) {\n    console.warn(\"[MapChannel] Failed to subscribe to family channel:\", error)\n  }\n\n  // Subscribe to points channel for real-time point updates (only if live mode is enabled)\n  if (enableLiveMode) {\n    try {\n      subscriptions.points = consumer.subscriptions.create(\"PointsChannel\", {\n        connected() {\n          console.log(\"PointsChannel connected\")\n          callbacks.connected?.(\"points\")\n        },\n\n        disconnected() {\n          console.log(\"PointsChannel disconnected\")\n          callbacks.disconnected?.(\"points\")\n        },\n\n        received(data) {\n          console.log(\"PointsChannel received:\", data)","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/Freika/dawarich/blob/97fad417c5a11b0eb11157890635e015723a2e97/app/javascript/maps_maplibre/channels/map_channel.js#L47-L83","documentation":"The map page subscribes to FamilyLocationsChannel inside a try/catch to receive live family-member locations. consumer.subscriptions.create throws synchronously when the consumer is in a bad state, the cable connection URL is wrong, or the channel identifier is malformed. When it throws, family live updates are unavailable for the session; points and tracks subscriptions still proceed.","triggerScenarios":"ActionCable mount path changed server-side so the cable URL 404s; the WebSocket to /cable failing CORS or blocked by a proxy that does not upgrade; the family features element present in the DOM but the channel identifier string not matching the Rails channel; a stale cached JS bundle calling a renamed channel.","commonSituations":"Reverse proxies (nginx/traefik) not passing Upgrade/Connection headers for the cable path; dev served over https while the cable URL uses ws:// (mixed content); backend channel renames during upgrades; older bundles cached by the browser or CDN.","solutions":["Open /cable in the browser — it must not 404, and the WS upgrade should appear as 101 Switching Protocols in the Network tab","Configure the proxy to pass Connection/Upgrade headers and allow long-lived connections for the cable path","Ensure Rails allowed_request_origins includes the site origin and the cable URL uses wss:// when the page is https","After backend deploys that touch channels, cache-bust stale JS bundles"],"exampleFix":"// before\nsubscriptions.family = consumer.subscriptions.create(\"FamilyLocationsChannel\", { ...handlers })\n// after\nif (typeof consumer?.subscriptions?.create === \"function\") {\n  subscriptions.family = consumer.subscriptions.create(\"FamilyLocationsChannel\", {\n    rejected() { console.warn(\"[MapChannel] Family channel rejected subscription\") },\n    ...handlers,\n  })\n}","handlingStrategy":"try-catch","validationCode":"if (!consumer || typeof consumer.subscriptions?.create !== \"function\") return\nconst familyEl = document.querySelector(\"[data-family-members-features-value]\")\nif (!familyEl) return // family feature disabled — skip the channel entirely","typeGuard":"/** @param {unknown} c @returns {boolean} */\nfunction isActionCableConsumer(c) {\n  return Boolean(\n    c &&\n    typeof c === \"object\" &&\n    typeof c.subscriptions?.create === \"function\"\n  )\n}","tryCatchPattern":"try {\n  subscriptions.family = consumer.subscriptions.create(\"FamilyLocationsChannel\", {\n    rejected() { console.warn(\"[MapChannel] Family channel rejected subscription\") },\n    ...handlers,\n  })\n} catch (error) {\n  console.warn(\"[MapChannel] Failed to subscribe to family channel:\", error)\n  // Realtime family locations are an enhancement: keep the map usable without them\n}","preventionTips":["Verify the WebSocket upgrade works for the cable endpoint in every environment — proxy configs differ","Add rejected() callbacks to subscriptions; server-side rejections do not throw and are otherwise invisible","Subscribe only when the corresponding feature-flag element exists in the DOM"],"tags":["actioncable","websocket","dawarich","family-locations","realtime"],"backgroundTag":"actioncable-subscription-failed","analyzedSha":"97fad417c5a11b0eb11157890635e015723a2e97","analyzedAt":"2026-08-21T17:04:17.778Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}